@hyperframes/producer 0.1.15 → 0.2.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2149,11 +2149,11 @@ function __extends(d, b) {
2149
2149
  }
2150
2150
  function __awaiter(thisArg, _arguments, P, generator) {
2151
2151
  function adopt(value) {
2152
- return value instanceof P ? value : new P(function(resolve12) {
2153
- resolve12(value);
2152
+ return value instanceof P ? value : new P(function(resolve13) {
2153
+ resolve13(value);
2154
2154
  });
2155
2155
  }
2156
- return new (P || (P = Promise))(function(resolve12, reject) {
2156
+ return new (P || (P = Promise))(function(resolve13, reject) {
2157
2157
  function fulfilled(value) {
2158
2158
  try {
2159
2159
  step(generator.next(value));
@@ -2169,7 +2169,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
2169
2169
  }
2170
2170
  }
2171
2171
  function step(result) {
2172
- result.done ? resolve12(result.value) : adopt(result.value).then(fulfilled, rejected);
2172
+ result.done ? resolve13(result.value) : adopt(result.value).then(fulfilled, rejected);
2173
2173
  }
2174
2174
  step((generator = generator.apply(thisArg, _arguments || [])).next());
2175
2175
  });
@@ -2332,14 +2332,14 @@ function __asyncValues(o) {
2332
2332
  }, i);
2333
2333
  function verb(n) {
2334
2334
  i[n] = o[n] && function(v) {
2335
- return new Promise(function(resolve12, reject) {
2336
- v = o[n](v), settle(resolve12, reject, v.done, v.value);
2335
+ return new Promise(function(resolve13, reject) {
2336
+ v = o[n](v), settle(resolve13, reject, v.done, v.value);
2337
2337
  });
2338
2338
  };
2339
2339
  }
2340
- function settle(resolve12, reject, d, v) {
2340
+ function settle(resolve13, reject, d, v) {
2341
2341
  Promise.resolve(v).then(function(v2) {
2342
- resolve12({ value: v2, done: d });
2342
+ resolve13({ value: v2, done: d });
2343
2343
  }, reject);
2344
2344
  }
2345
2345
  }
@@ -2864,7 +2864,7 @@ function of() {
2864
2864
  }
2865
2865
  function lastValueFrom(source2, config2) {
2866
2866
  var hasConfig = typeof config2 === "object";
2867
- return new Promise(function(resolve12, reject) {
2867
+ return new Promise(function(resolve13, reject) {
2868
2868
  var _hasValue = false;
2869
2869
  var _value;
2870
2870
  source2.subscribe({
@@ -2875,9 +2875,9 @@ function lastValueFrom(source2, config2) {
2875
2875
  error: reject,
2876
2876
  complete: function() {
2877
2877
  if (_hasValue) {
2878
- resolve12(_value);
2878
+ resolve13(_value);
2879
2879
  } else if (hasConfig) {
2880
- resolve12(config2.defaultValue);
2880
+ resolve13(config2.defaultValue);
2881
2881
  } else {
2882
2882
  reject(new EmptyError());
2883
2883
  }
@@ -2887,16 +2887,16 @@ function lastValueFrom(source2, config2) {
2887
2887
  }
2888
2888
  function firstValueFrom(source2, config2) {
2889
2889
  var hasConfig = typeof config2 === "object";
2890
- return new Promise(function(resolve12, reject) {
2890
+ return new Promise(function(resolve13, reject) {
2891
2891
  var subscriber = new SafeSubscriber({
2892
2892
  next: function(value) {
2893
- resolve12(value);
2893
+ resolve13(value);
2894
2894
  subscriber.unsubscribe();
2895
2895
  },
2896
2896
  error: reject,
2897
2897
  complete: function() {
2898
2898
  if (hasConfig) {
2899
- resolve12(config2.defaultValue);
2899
+ resolve13(config2.defaultValue);
2900
2900
  } else {
2901
2901
  reject(new EmptyError());
2902
2902
  }
@@ -3935,7 +3935,7 @@ var init_rxjs = __esm({
3935
3935
  Observable2.prototype.forEach = function(next, promiseCtor) {
3936
3936
  var _this = this;
3937
3937
  promiseCtor = getPromiseCtor(promiseCtor);
3938
- return new promiseCtor(function(resolve12, reject) {
3938
+ return new promiseCtor(function(resolve13, reject) {
3939
3939
  var subscriber = new SafeSubscriber({
3940
3940
  next: function(value) {
3941
3941
  try {
@@ -3946,7 +3946,7 @@ var init_rxjs = __esm({
3946
3946
  }
3947
3947
  },
3948
3948
  error: reject,
3949
- complete: resolve12
3949
+ complete: resolve13
3950
3950
  });
3951
3951
  _this.subscribe(subscriber);
3952
3952
  });
@@ -3968,14 +3968,14 @@ var init_rxjs = __esm({
3968
3968
  Observable2.prototype.toPromise = function(promiseCtor) {
3969
3969
  var _this = this;
3970
3970
  promiseCtor = getPromiseCtor(promiseCtor);
3971
- return new promiseCtor(function(resolve12, reject) {
3971
+ return new promiseCtor(function(resolve13, reject) {
3972
3972
  var value;
3973
3973
  _this.subscribe(function(x) {
3974
3974
  return value = x;
3975
3975
  }, function(err) {
3976
3976
  return reject(err);
3977
3977
  }, function() {
3978
- return resolve12(value);
3978
+ return resolve13(value);
3979
3979
  });
3980
3980
  });
3981
3981
  };
@@ -6405,8 +6405,8 @@ var init_Deferred = __esm({
6405
6405
  // SAFETY: This is ensured by #taskPromise.
6406
6406
  #resolve;
6407
6407
  // TODO: Switch to Promise.withResolvers with Node 22
6408
- #taskPromise = new Promise((resolve12) => {
6409
- this.#resolve = resolve12;
6408
+ #taskPromise = new Promise((resolve13) => {
6409
+ this.#resolve = resolve13;
6410
6410
  });
6411
6411
  #timeoutId;
6412
6412
  #timeoutError;
@@ -6496,12 +6496,12 @@ var init_Mutex = __esm({
6496
6496
  return new _Mutex.Guard(this, onRelease);
6497
6497
  }
6498
6498
  release() {
6499
- const resolve12 = this.#acquirers.shift();
6500
- if (!resolve12) {
6499
+ const resolve13 = this.#acquirers.shift();
6500
+ if (!resolve13) {
6501
6501
  this.#locked = false;
6502
6502
  return;
6503
6503
  }
6504
- resolve12();
6504
+ resolve13();
6505
6505
  }
6506
6506
  };
6507
6507
  }
@@ -8516,12 +8516,12 @@ var init_locators = __esm({
8516
8516
  }
8517
8517
  return defer(() => {
8518
8518
  return from(handle.evaluate((element) => {
8519
- return new Promise((resolve12) => {
8519
+ return new Promise((resolve13) => {
8520
8520
  window.requestAnimationFrame(() => {
8521
8521
  const rect1 = element.getBoundingClientRect();
8522
8522
  window.requestAnimationFrame(() => {
8523
8523
  const rect2 = element.getBoundingClientRect();
8524
- resolve12([
8524
+ resolve13([
8525
8525
  {
8526
8526
  x: rect1.x,
8527
8527
  y: rect1.y,
@@ -10260,9 +10260,9 @@ var init_ElementHandle = __esm({
10260
10260
  const handle = await this.#asSVGElementHandle();
10261
10261
  const target = __addDisposableResource6(env_5, handle && await handle.#getOwnerSVGElement(), false);
10262
10262
  return await (target ?? this).evaluate(async (element, threshold) => {
10263
- const visibleRatio = await new Promise((resolve12) => {
10263
+ const visibleRatio = await new Promise((resolve13) => {
10264
10264
  const observer = new IntersectionObserver((entries2) => {
10265
- resolve12(entries2[0].intersectionRatio);
10265
+ resolve13(entries2[0].intersectionRatio);
10266
10266
  observer.disconnect();
10267
10267
  });
10268
10268
  observer.observe(element);
@@ -10908,7 +10908,7 @@ var init_Frame = __esm({
10908
10908
  }
10909
10909
  type = type ?? "text/javascript";
10910
10910
  return await this.mainRealm().transferHandle(await this.isolatedRealm().evaluateHandle(async ({ url, id, type: type2, content: content2 }) => {
10911
- return await new Promise((resolve12, reject) => {
10911
+ return await new Promise((resolve13, reject) => {
10912
10912
  const script = document.createElement("script");
10913
10913
  script.type = type2;
10914
10914
  script.text = content2;
@@ -10921,12 +10921,12 @@ var init_Frame = __esm({
10921
10921
  if (url) {
10922
10922
  script.src = url;
10923
10923
  script.addEventListener("load", () => {
10924
- resolve12(script);
10924
+ resolve13(script);
10925
10925
  }, { once: true });
10926
10926
  document.head.appendChild(script);
10927
10927
  } else {
10928
10928
  document.head.appendChild(script);
10929
- resolve12(script);
10929
+ resolve13(script);
10930
10930
  }
10931
10931
  });
10932
10932
  }, { ...options, type, content }));
@@ -10946,7 +10946,7 @@ var init_Frame = __esm({
10946
10946
  options.content = content;
10947
10947
  }
10948
10948
  return await this.mainRealm().transferHandle(await this.isolatedRealm().evaluateHandle(async ({ url, content: content2 }) => {
10949
- return await new Promise((resolve12, reject) => {
10949
+ return await new Promise((resolve13, reject) => {
10950
10950
  let element;
10951
10951
  if (!url) {
10952
10952
  element = document.createElement("style");
@@ -10958,7 +10958,7 @@ var init_Frame = __esm({
10958
10958
  element = link;
10959
10959
  }
10960
10960
  element.addEventListener("load", () => {
10961
- resolve12(element);
10961
+ resolve13(element);
10962
10962
  }, { once: true });
10963
10963
  element.addEventListener("error", (event) => {
10964
10964
  reject(new Error(event.message ?? "Could not load style"));
@@ -12697,9 +12697,9 @@ var init_Page = __esm({
12697
12697
  ++this.#screencastSessionCount;
12698
12698
  if (!this.#startScreencastPromise) {
12699
12699
  this.#startScreencastPromise = this.mainFrame().client.send("Page.startScreencast", { format: "png" }).then(() => {
12700
- return new Promise((resolve12) => {
12700
+ return new Promise((resolve13) => {
12701
12701
  return this.mainFrame().client.once("Page.screencastFrame", () => {
12702
- return resolve12();
12702
+ return resolve13();
12703
12703
  });
12704
12704
  });
12705
12705
  });
@@ -16017,11 +16017,11 @@ function addPageBinding(type, name, prefix) {
16017
16017
  return value instanceof Node;
16018
16018
  })
16019
16019
  }));
16020
- return new Promise((resolve12, reject) => {
16020
+ return new Promise((resolve13, reject) => {
16021
16021
  callPuppeteer.callbacks.set(seq, {
16022
16022
  resolve(value) {
16023
16023
  callPuppeteer.args.delete(seq);
16024
- resolve12(value);
16024
+ resolve13(value);
16025
16025
  },
16026
16026
  reject(value) {
16027
16027
  callPuppeteer.args.delete(seq);
@@ -19684,8 +19684,8 @@ var init_Input2 = __esm({
19684
19684
  if (typeof delay === "number") {
19685
19685
  await Promise.all(actions);
19686
19686
  actions.length = 0;
19687
- await new Promise((resolve12) => {
19688
- setTimeout(resolve12, delay);
19687
+ await new Promise((resolve13) => {
19688
+ setTimeout(resolve13, delay);
19689
19689
  });
19690
19690
  }
19691
19691
  actions.push(this.up({ ...options, clickCount }));
@@ -19705,9 +19705,9 @@ var init_Input2 = __esm({
19705
19705
  });
19706
19706
  }
19707
19707
  async drag(start, target) {
19708
- const promise = new Promise((resolve12) => {
19708
+ const promise = new Promise((resolve13) => {
19709
19709
  this.#client.once("Input.dragIntercepted", (event) => {
19710
- return resolve12(event.data);
19710
+ return resolve13(event.data);
19711
19711
  });
19712
19712
  });
19713
19713
  await this.move(start.x, start.y);
@@ -19748,8 +19748,8 @@ var init_Input2 = __esm({
19748
19748
  await this.dragEnter(target, data);
19749
19749
  await this.dragOver(target, data);
19750
19750
  if (delay) {
19751
- await new Promise((resolve12) => {
19752
- return setTimeout(resolve12, delay);
19751
+ await new Promise((resolve13) => {
19752
+ return setTimeout(resolve13, delay);
19753
19753
  });
19754
19754
  }
19755
19755
  await this.drop(target, data);
@@ -20633,9 +20633,9 @@ var init_Page2 = __esm({
20633
20633
  async captureHeapSnapshot(options) {
20634
20634
  const { createWriteStream: createWriteStream3 } = environment.value.fs;
20635
20635
  const stream2 = createWriteStream3(options.path);
20636
- const streamPromise = new Promise((resolve12, reject) => {
20636
+ const streamPromise = new Promise((resolve13, reject) => {
20637
20637
  stream2.on("error", reject);
20638
- stream2.on("finish", resolve12);
20638
+ stream2.on("finish", resolve13);
20639
20639
  });
20640
20640
  const client = this.#primaryTargetClient;
20641
20641
  await client.send("HeapProfiler.enable");
@@ -22277,10 +22277,10 @@ var init_BrowserWebSocketTransport = __esm({
22277
22277
  "../../node_modules/.bun/puppeteer-core@24.40.0/node_modules/puppeteer-core/lib/esm/puppeteer/common/BrowserWebSocketTransport.js"() {
22278
22278
  BrowserWebSocketTransport = class _BrowserWebSocketTransport {
22279
22279
  static create(url) {
22280
- return new Promise((resolve12, reject) => {
22280
+ return new Promise((resolve13, reject) => {
22281
22281
  const ws = new WebSocket(url);
22282
22282
  ws.addEventListener("open", () => {
22283
- return resolve12(new _BrowserWebSocketTransport(ws));
22283
+ return resolve13(new _BrowserWebSocketTransport(ws));
22284
22284
  });
22285
22285
  ws.addEventListener("error", reject);
22286
22286
  });
@@ -25202,11 +25202,11 @@ var require_BrowsingContextProcessor = __commonJS({
25202
25202
  }
25203
25203
  const parentCdpClient = context2.cdpTarget.parentCdpClient;
25204
25204
  try {
25205
- const detachedFromTargetPromise = new Promise((resolve12) => {
25205
+ const detachedFromTargetPromise = new Promise((resolve13) => {
25206
25206
  const onContextDestroyed = (event) => {
25207
25207
  if (event.targetId === params.context) {
25208
25208
  parentCdpClient.off("Target.detachedFromTarget", onContextDestroyed);
25209
- resolve12();
25209
+ resolve13();
25210
25210
  }
25211
25211
  };
25212
25212
  parentCdpClient.on("Target.detachedFromTarget", onContextDestroyed);
@@ -26569,7 +26569,7 @@ var require_ActionDispatcher = __commonJS({
26569
26569
  }
26570
26570
  }
26571
26571
  const promises = [
26572
- new Promise((resolve12) => setTimeout(resolve12, this.#tickDuration))
26572
+ new Promise((resolve13) => setTimeout(resolve13, this.#tickDuration))
26573
26573
  ];
26574
26574
  for (const option of options) {
26575
26575
  promises.push(this.#dispatchAction(option));
@@ -27170,8 +27170,8 @@ var require_Mutex = __commonJS({
27170
27170
  acquire() {
27171
27171
  const state = { resolved: false };
27172
27172
  if (this.#locked) {
27173
- return new Promise((resolve12) => {
27174
- this.#acquirers.push(() => resolve12(this.#release.bind(this, state)));
27173
+ return new Promise((resolve13) => {
27174
+ this.#acquirers.push(() => resolve13(this.#release.bind(this, state)));
27175
27175
  });
27176
27176
  }
27177
27177
  this.#locked = true;
@@ -27182,12 +27182,12 @@ var require_Mutex = __commonJS({
27182
27182
  throw new Error("Cannot release more than once.");
27183
27183
  }
27184
27184
  state.resolved = true;
27185
- const resolve12 = this.#acquirers.shift();
27186
- if (!resolve12) {
27185
+ const resolve13 = this.#acquirers.shift();
27186
+ if (!resolve13) {
27187
27187
  this.#locked = false;
27188
27188
  return;
27189
27189
  }
27190
- resolve12();
27190
+ resolve13();
27191
27191
  }
27192
27192
  async run(action) {
27193
27193
  const release = await this.acquire();
@@ -28369,8 +28369,8 @@ var require_ChannelProxy = __commonJS({
28369
28369
  * in the queue.
28370
28370
  */
28371
28371
  async getMessage() {
28372
- const onMessage = queue.length > 0 ? Promise.resolve() : new Promise((resolve12) => {
28373
- queueNonEmptyResolver = resolve12;
28372
+ const onMessage = queue.length > 0 ? Promise.resolve() : new Promise((resolve13) => {
28373
+ queueNonEmptyResolver = resolve13;
28374
28374
  });
28375
28375
  await onMessage;
28376
28376
  return queue.shift();
@@ -28475,7 +28475,7 @@ var require_ChannelProxy = __commonJS({
28475
28475
  functionDeclaration: String((id) => {
28476
28476
  const w = window;
28477
28477
  if (w[id] === void 0) {
28478
- return new Promise((resolve12) => w[id] = resolve12);
28478
+ return new Promise((resolve13) => w[id] = resolve13);
28479
28479
  }
28480
28480
  const channelProxy = w[id];
28481
28481
  delete w[id];
@@ -29976,8 +29976,8 @@ var require_Deferred = __commonJS({
29976
29976
  return this.#result;
29977
29977
  }
29978
29978
  constructor() {
29979
- this.#promise = new Promise((resolve12, reject) => {
29980
- this.#resolve = resolve12;
29979
+ this.#promise = new Promise((resolve13, reject) => {
29980
+ this.#resolve = resolve13;
29981
29981
  this.#reject = reject;
29982
29982
  });
29983
29983
  this.#promise.catch((_error) => {
@@ -34821,11 +34821,11 @@ var require_BrowsingContextStorage = __commonJS({
34821
34821
  if (this.#contexts.has(browsingContextId)) {
34822
34822
  return Promise.resolve(this.getContext(browsingContextId));
34823
34823
  }
34824
- return new Promise((resolve12) => {
34824
+ return new Promise((resolve13) => {
34825
34825
  const listener = (event) => {
34826
34826
  if (event.browsingContext.id === browsingContextId) {
34827
34827
  this.#eventEmitter.off("added", listener);
34828
- resolve12(event.browsingContext);
34828
+ resolve13(event.browsingContext);
34829
34829
  }
34830
34830
  };
34831
34831
  this.#eventEmitter.on("added", listener);
@@ -38407,8 +38407,8 @@ var init_ExposedFunction = __esm({
38407
38407
  const functionDeclaration = stringifyFunction(interpolateFunction((callback) => {
38408
38408
  Object.assign(globalThis, {
38409
38409
  [PLACEHOLDER("name")]: function(...args) {
38410
- return new Promise((resolve12, reject) => {
38411
- callback([resolve12, reject, args]);
38410
+ return new Promise((resolve13, reject) => {
38411
+ callback([resolve13, reject, args]);
38412
38412
  });
38413
38413
  }
38414
38414
  });
@@ -38496,8 +38496,8 @@ var init_ExposedFunction = __esm({
38496
38496
  return;
38497
38497
  }
38498
38498
  try {
38499
- await dataHandle.evaluate(([resolve12], result2) => {
38500
- resolve12(result2);
38499
+ await dataHandle.evaluate(([resolve13], result2) => {
38500
+ resolve13(result2);
38501
38501
  }, result);
38502
38502
  } catch (error) {
38503
38503
  debugError(error);
@@ -46578,7 +46578,7 @@ var init_NodeWebSocketTransport = __esm({
46578
46578
  init_version();
46579
46579
  NodeWebSocketTransport = class _NodeWebSocketTransport {
46580
46580
  static create(url, headers) {
46581
- return new Promise((resolve12, reject) => {
46581
+ return new Promise((resolve13, reject) => {
46582
46582
  const ws = new wrapper_default(url, [], {
46583
46583
  followRedirects: true,
46584
46584
  perMessageDeflate: false,
@@ -46591,7 +46591,7 @@ var init_NodeWebSocketTransport = __esm({
46591
46591
  }
46592
46592
  });
46593
46593
  ws.addEventListener("open", () => {
46594
- return resolve12(new _NodeWebSocketTransport(ws));
46594
+ return resolve13(new _NodeWebSocketTransport(ws));
46595
46595
  });
46596
46596
  ws.addEventListener("error", reject);
46597
46597
  });
@@ -49652,8 +49652,8 @@ var require_helpers = __commonJS({
49652
49652
  function req(url, opts = {}) {
49653
49653
  const href = typeof url === "string" ? url : url.href;
49654
49654
  const req2 = (href.startsWith("https:") ? https2 : http2).request(url, opts);
49655
- const promise = new Promise((resolve12, reject) => {
49656
- req2.once("response", resolve12).once("error", reject).end();
49655
+ const promise = new Promise((resolve13, reject) => {
49656
+ req2.once("response", resolve13).once("error", reject).end();
49657
49657
  });
49658
49658
  req2.then = promise.then.bind(promise);
49659
49659
  return req2;
@@ -50030,7 +50030,7 @@ var require_parse_proxy_response = __commonJS({
50030
50030
  var debug_1 = __importDefault2(require_src());
50031
50031
  var debug6 = (0, debug_1.default)("https-proxy-agent:parse-proxy-response");
50032
50032
  function parseProxyResponse(socket) {
50033
- return new Promise((resolve12, reject) => {
50033
+ return new Promise((resolve13, reject) => {
50034
50034
  let buffersLength = 0;
50035
50035
  const buffers = [];
50036
50036
  function read() {
@@ -50096,7 +50096,7 @@ var require_parse_proxy_response = __commonJS({
50096
50096
  }
50097
50097
  debug6("got proxy server response: %o %o", firstLine, headers);
50098
50098
  cleanup();
50099
- resolve12({
50099
+ resolve13({
50100
50100
  connect: {
50101
50101
  statusCode,
50102
50102
  statusText,
@@ -53354,11 +53354,11 @@ var require_socksclient = __commonJS({
53354
53354
  "use strict";
53355
53355
  var __awaiter3 = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
53356
53356
  function adopt(value) {
53357
- return value instanceof P ? value : new P(function(resolve12) {
53358
- resolve12(value);
53357
+ return value instanceof P ? value : new P(function(resolve13) {
53358
+ resolve13(value);
53359
53359
  });
53360
53360
  }
53361
- return new (P || (P = Promise))(function(resolve12, reject) {
53361
+ return new (P || (P = Promise))(function(resolve13, reject) {
53362
53362
  function fulfilled(value) {
53363
53363
  try {
53364
53364
  step(generator.next(value));
@@ -53374,7 +53374,7 @@ var require_socksclient = __commonJS({
53374
53374
  }
53375
53375
  }
53376
53376
  function step(result) {
53377
- result.done ? resolve12(result.value) : adopt(result.value).then(fulfilled, rejected);
53377
+ result.done ? resolve13(result.value) : adopt(result.value).then(fulfilled, rejected);
53378
53378
  }
53379
53379
  step((generator = generator.apply(thisArg, _arguments || [])).next());
53380
53380
  });
@@ -53408,13 +53408,13 @@ var require_socksclient = __commonJS({
53408
53408
  * @returns { Promise }
53409
53409
  */
53410
53410
  static createConnection(options, callback) {
53411
- return new Promise((resolve12, reject) => {
53411
+ return new Promise((resolve13, reject) => {
53412
53412
  try {
53413
53413
  (0, helpers_1.validateSocksClientOptions)(options, ["connect"]);
53414
53414
  } catch (err) {
53415
53415
  if (typeof callback === "function") {
53416
53416
  callback(err);
53417
- return resolve12(err);
53417
+ return resolve13(err);
53418
53418
  } else {
53419
53419
  return reject(err);
53420
53420
  }
@@ -53425,16 +53425,16 @@ var require_socksclient = __commonJS({
53425
53425
  client.removeAllListeners();
53426
53426
  if (typeof callback === "function") {
53427
53427
  callback(null, info);
53428
- resolve12(info);
53428
+ resolve13(info);
53429
53429
  } else {
53430
- resolve12(info);
53430
+ resolve13(info);
53431
53431
  }
53432
53432
  });
53433
53433
  client.once("error", (err) => {
53434
53434
  client.removeAllListeners();
53435
53435
  if (typeof callback === "function") {
53436
53436
  callback(err);
53437
- resolve12(err);
53437
+ resolve13(err);
53438
53438
  } else {
53439
53439
  reject(err);
53440
53440
  }
@@ -53451,13 +53451,13 @@ var require_socksclient = __commonJS({
53451
53451
  * @returns { Promise }
53452
53452
  */
53453
53453
  static createConnectionChain(options, callback) {
53454
- return new Promise((resolve12, reject) => __awaiter3(this, void 0, void 0, function* () {
53454
+ return new Promise((resolve13, reject) => __awaiter3(this, void 0, void 0, function* () {
53455
53455
  try {
53456
53456
  (0, helpers_1.validateSocksClientChainOptions)(options);
53457
53457
  } catch (err) {
53458
53458
  if (typeof callback === "function") {
53459
53459
  callback(err);
53460
- return resolve12(err);
53460
+ return resolve13(err);
53461
53461
  } else {
53462
53462
  return reject(err);
53463
53463
  }
@@ -53483,14 +53483,14 @@ var require_socksclient = __commonJS({
53483
53483
  }
53484
53484
  if (typeof callback === "function") {
53485
53485
  callback(null, { socket: sock });
53486
- resolve12({ socket: sock });
53486
+ resolve13({ socket: sock });
53487
53487
  } else {
53488
- resolve12({ socket: sock });
53488
+ resolve13({ socket: sock });
53489
53489
  }
53490
53490
  } catch (err) {
53491
53491
  if (typeof callback === "function") {
53492
53492
  callback(err);
53493
- resolve12(err);
53493
+ resolve13(err);
53494
53494
  } else {
53495
53495
  reject(err);
53496
53496
  }
@@ -54174,12 +54174,12 @@ var require_dist4 = __commonJS({
54174
54174
  let { host } = opts;
54175
54175
  const { port, lookup: lookupFn = dns.lookup } = opts;
54176
54176
  if (shouldLookup) {
54177
- host = await new Promise((resolve12, reject) => {
54177
+ host = await new Promise((resolve13, reject) => {
54178
54178
  lookupFn(host, {}, (err, res) => {
54179
54179
  if (err) {
54180
54180
  reject(err);
54181
54181
  } else {
54182
- resolve12(res);
54182
+ resolve13(res);
54183
54183
  }
54184
54184
  });
54185
54185
  });
@@ -55364,7 +55364,7 @@ var require_netUtils = __commonJS({
55364
55364
  return `${socket.remoteAddress}:${socket.remotePort}`;
55365
55365
  }
55366
55366
  function upgradeSocket(socket, options) {
55367
- return new Promise((resolve12, reject) => {
55367
+ return new Promise((resolve13, reject) => {
55368
55368
  const tlsOptions = Object.assign({}, options, {
55369
55369
  socket
55370
55370
  });
@@ -55374,7 +55374,7 @@ var require_netUtils = __commonJS({
55374
55374
  reject(tlsSocket.authorizationError);
55375
55375
  } else {
55376
55376
  tlsSocket.removeAllListeners("error");
55377
- resolve12(tlsSocket);
55377
+ resolve13(tlsSocket);
55378
55378
  }
55379
55379
  }).once("error", (error) => {
55380
55380
  reject(error);
@@ -55469,7 +55469,7 @@ var require_transfer = __commonJS({
55469
55469
  };
55470
55470
  }
55471
55471
  function connectForPassiveTransfer(host, port, ftp) {
55472
- return new Promise((resolve12, reject) => {
55472
+ return new Promise((resolve13, reject) => {
55473
55473
  let socket = ftp._newSocket();
55474
55474
  const handleConnErr = function(err) {
55475
55475
  err.message = "Can't open data connection in passive mode: " + err.message;
@@ -55497,7 +55497,7 @@ var require_transfer = __commonJS({
55497
55497
  socket.removeListener("error", handleConnErr);
55498
55498
  socket.removeListener("timeout", handleTimeout);
55499
55499
  ftp.dataSocket = socket;
55500
- resolve12();
55500
+ resolve13();
55501
55501
  });
55502
55502
  });
55503
55503
  }
@@ -57895,7 +57895,7 @@ var require_util2 = __commonJS({
57895
57895
  return path12;
57896
57896
  }
57897
57897
  exports.normalize = normalize2;
57898
- function join16(aRoot, aPath) {
57898
+ function join17(aRoot, aPath) {
57899
57899
  if (aRoot === "") {
57900
57900
  aRoot = ".";
57901
57901
  }
@@ -57927,7 +57927,7 @@ var require_util2 = __commonJS({
57927
57927
  }
57928
57928
  return joined;
57929
57929
  }
57930
- exports.join = join16;
57930
+ exports.join = join17;
57931
57931
  exports.isAbsolute = function(aPath) {
57932
57932
  return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
57933
57933
  };
@@ -58100,7 +58100,7 @@ var require_util2 = __commonJS({
58100
58100
  parsed.path = parsed.path.substring(0, index + 1);
58101
58101
  }
58102
58102
  }
58103
- sourceURL = join16(urlGenerate(parsed), sourceURL);
58103
+ sourceURL = join17(urlGenerate(parsed), sourceURL);
58104
58104
  }
58105
58105
  return normalize2(sourceURL);
58106
58106
  }
@@ -59902,7 +59902,7 @@ var require_escodegen = __commonJS({
59902
59902
  function noEmptySpace() {
59903
59903
  return space ? space : " ";
59904
59904
  }
59905
- function join16(left2, right2) {
59905
+ function join17(left2, right2) {
59906
59906
  var leftSource, rightSource, leftCharCode, rightCharCode;
59907
59907
  leftSource = toSourceNodeWhenNeeded(left2).toString();
59908
59908
  if (leftSource.length === 0) {
@@ -60233,8 +60233,8 @@ var require_escodegen = __commonJS({
60233
60233
  } else {
60234
60234
  result.push(that.generateExpression(stmt.left, Precedence.Call, E_TTT));
60235
60235
  }
60236
- result = join16(result, operator);
60237
- result = [join16(
60236
+ result = join17(result, operator);
60237
+ result = [join17(
60238
60238
  result,
60239
60239
  that.generateExpression(stmt.right, Precedence.Assignment, E_TTT)
60240
60240
  ), ")"];
@@ -60377,11 +60377,11 @@ var require_escodegen = __commonJS({
60377
60377
  var result, fragment;
60378
60378
  result = ["class"];
60379
60379
  if (stmt.id) {
60380
- result = join16(result, this.generateExpression(stmt.id, Precedence.Sequence, E_TTT));
60380
+ result = join17(result, this.generateExpression(stmt.id, Precedence.Sequence, E_TTT));
60381
60381
  }
60382
60382
  if (stmt.superClass) {
60383
- fragment = join16("extends", this.generateExpression(stmt.superClass, Precedence.Unary, E_TTT));
60384
- result = join16(result, fragment);
60383
+ fragment = join17("extends", this.generateExpression(stmt.superClass, Precedence.Unary, E_TTT));
60384
+ result = join17(result, fragment);
60385
60385
  }
60386
60386
  result.push(space);
60387
60387
  result.push(this.generateStatement(stmt.body, S_TFFT));
@@ -60394,9 +60394,9 @@ var require_escodegen = __commonJS({
60394
60394
  return escapeDirective(stmt.directive) + this.semicolon(flags);
60395
60395
  },
60396
60396
  DoWhileStatement: function(stmt, flags) {
60397
- var result = join16("do", this.maybeBlock(stmt.body, S_TFFF));
60397
+ var result = join17("do", this.maybeBlock(stmt.body, S_TFFF));
60398
60398
  result = this.maybeBlockSuffix(stmt.body, result);
60399
- return join16(result, [
60399
+ return join17(result, [
60400
60400
  "while" + space + "(",
60401
60401
  this.generateExpression(stmt.test, Precedence.Sequence, E_TTT),
60402
60402
  ")" + this.semicolon(flags)
@@ -60432,11 +60432,11 @@ var require_escodegen = __commonJS({
60432
60432
  ExportDefaultDeclaration: function(stmt, flags) {
60433
60433
  var result = ["export"], bodyFlags;
60434
60434
  bodyFlags = flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF;
60435
- result = join16(result, "default");
60435
+ result = join17(result, "default");
60436
60436
  if (isStatement(stmt.declaration)) {
60437
- result = join16(result, this.generateStatement(stmt.declaration, bodyFlags));
60437
+ result = join17(result, this.generateStatement(stmt.declaration, bodyFlags));
60438
60438
  } else {
60439
- result = join16(result, this.generateExpression(stmt.declaration, Precedence.Assignment, E_TTT) + this.semicolon(flags));
60439
+ result = join17(result, this.generateExpression(stmt.declaration, Precedence.Assignment, E_TTT) + this.semicolon(flags));
60440
60440
  }
60441
60441
  return result;
60442
60442
  },
@@ -60444,15 +60444,15 @@ var require_escodegen = __commonJS({
60444
60444
  var result = ["export"], bodyFlags, that = this;
60445
60445
  bodyFlags = flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF;
60446
60446
  if (stmt.declaration) {
60447
- return join16(result, this.generateStatement(stmt.declaration, bodyFlags));
60447
+ return join17(result, this.generateStatement(stmt.declaration, bodyFlags));
60448
60448
  }
60449
60449
  if (stmt.specifiers) {
60450
60450
  if (stmt.specifiers.length === 0) {
60451
- result = join16(result, "{" + space + "}");
60451
+ result = join17(result, "{" + space + "}");
60452
60452
  } else if (stmt.specifiers[0].type === Syntax.ExportBatchSpecifier) {
60453
- result = join16(result, this.generateExpression(stmt.specifiers[0], Precedence.Sequence, E_TTT));
60453
+ result = join17(result, this.generateExpression(stmt.specifiers[0], Precedence.Sequence, E_TTT));
60454
60454
  } else {
60455
- result = join16(result, "{");
60455
+ result = join17(result, "{");
60456
60456
  withIndent(function(indent2) {
60457
60457
  var i, iz;
60458
60458
  result.push(newline);
@@ -60470,7 +60470,7 @@ var require_escodegen = __commonJS({
60470
60470
  result.push(base + "}");
60471
60471
  }
60472
60472
  if (stmt.source) {
60473
- result = join16(result, [
60473
+ result = join17(result, [
60474
60474
  "from" + space,
60475
60475
  // ModuleSpecifier
60476
60476
  this.generateExpression(stmt.source, Precedence.Sequence, E_TTT),
@@ -60558,7 +60558,7 @@ var require_escodegen = __commonJS({
60558
60558
  ];
60559
60559
  cursor = 0;
60560
60560
  if (stmt.specifiers[cursor].type === Syntax.ImportDefaultSpecifier) {
60561
- result = join16(result, [
60561
+ result = join17(result, [
60562
60562
  this.generateExpression(stmt.specifiers[cursor], Precedence.Sequence, E_TTT)
60563
60563
  ]);
60564
60564
  ++cursor;
@@ -60568,7 +60568,7 @@ var require_escodegen = __commonJS({
60568
60568
  result.push(",");
60569
60569
  }
60570
60570
  if (stmt.specifiers[cursor].type === Syntax.ImportNamespaceSpecifier) {
60571
- result = join16(result, [
60571
+ result = join17(result, [
60572
60572
  space,
60573
60573
  this.generateExpression(stmt.specifiers[cursor], Precedence.Sequence, E_TTT)
60574
60574
  ]);
@@ -60597,7 +60597,7 @@ var require_escodegen = __commonJS({
60597
60597
  }
60598
60598
  }
60599
60599
  }
60600
- result = join16(result, [
60600
+ result = join17(result, [
60601
60601
  "from" + space,
60602
60602
  // ModuleSpecifier
60603
60603
  this.generateExpression(stmt.source, Precedence.Sequence, E_TTT),
@@ -60651,7 +60651,7 @@ var require_escodegen = __commonJS({
60651
60651
  return result;
60652
60652
  },
60653
60653
  ThrowStatement: function(stmt, flags) {
60654
- return [join16(
60654
+ return [join17(
60655
60655
  "throw",
60656
60656
  this.generateExpression(stmt.argument, Precedence.Sequence, E_TTT)
60657
60657
  ), this.semicolon(flags)];
@@ -60662,7 +60662,7 @@ var require_escodegen = __commonJS({
60662
60662
  result = this.maybeBlockSuffix(stmt.block, result);
60663
60663
  if (stmt.handlers) {
60664
60664
  for (i = 0, iz = stmt.handlers.length; i < iz; ++i) {
60665
- result = join16(result, this.generateStatement(stmt.handlers[i], S_TFFF));
60665
+ result = join17(result, this.generateStatement(stmt.handlers[i], S_TFFF));
60666
60666
  if (stmt.finalizer || i + 1 !== iz) {
60667
60667
  result = this.maybeBlockSuffix(stmt.handlers[i].body, result);
60668
60668
  }
@@ -60670,7 +60670,7 @@ var require_escodegen = __commonJS({
60670
60670
  } else {
60671
60671
  guardedHandlers = stmt.guardedHandlers || [];
60672
60672
  for (i = 0, iz = guardedHandlers.length; i < iz; ++i) {
60673
- result = join16(result, this.generateStatement(guardedHandlers[i], S_TFFF));
60673
+ result = join17(result, this.generateStatement(guardedHandlers[i], S_TFFF));
60674
60674
  if (stmt.finalizer || i + 1 !== iz) {
60675
60675
  result = this.maybeBlockSuffix(guardedHandlers[i].body, result);
60676
60676
  }
@@ -60678,13 +60678,13 @@ var require_escodegen = __commonJS({
60678
60678
  if (stmt.handler) {
60679
60679
  if (Array.isArray(stmt.handler)) {
60680
60680
  for (i = 0, iz = stmt.handler.length; i < iz; ++i) {
60681
- result = join16(result, this.generateStatement(stmt.handler[i], S_TFFF));
60681
+ result = join17(result, this.generateStatement(stmt.handler[i], S_TFFF));
60682
60682
  if (stmt.finalizer || i + 1 !== iz) {
60683
60683
  result = this.maybeBlockSuffix(stmt.handler[i].body, result);
60684
60684
  }
60685
60685
  }
60686
60686
  } else {
60687
- result = join16(result, this.generateStatement(stmt.handler, S_TFFF));
60687
+ result = join17(result, this.generateStatement(stmt.handler, S_TFFF));
60688
60688
  if (stmt.finalizer) {
60689
60689
  result = this.maybeBlockSuffix(stmt.handler.body, result);
60690
60690
  }
@@ -60692,7 +60692,7 @@ var require_escodegen = __commonJS({
60692
60692
  }
60693
60693
  }
60694
60694
  if (stmt.finalizer) {
60695
- result = join16(result, ["finally", this.maybeBlock(stmt.finalizer, S_TFFF)]);
60695
+ result = join17(result, ["finally", this.maybeBlock(stmt.finalizer, S_TFFF)]);
60696
60696
  }
60697
60697
  return result;
60698
60698
  },
@@ -60726,7 +60726,7 @@ var require_escodegen = __commonJS({
60726
60726
  withIndent(function() {
60727
60727
  if (stmt.test) {
60728
60728
  result = [
60729
- join16("case", that.generateExpression(stmt.test, Precedence.Sequence, E_TTT)),
60729
+ join17("case", that.generateExpression(stmt.test, Precedence.Sequence, E_TTT)),
60730
60730
  ":"
60731
60731
  ];
60732
60732
  } else {
@@ -60774,9 +60774,9 @@ var require_escodegen = __commonJS({
60774
60774
  result.push(this.maybeBlock(stmt.consequent, S_TFFF));
60775
60775
  result = this.maybeBlockSuffix(stmt.consequent, result);
60776
60776
  if (stmt.alternate.type === Syntax.IfStatement) {
60777
- result = join16(result, ["else ", this.generateStatement(stmt.alternate, bodyFlags)]);
60777
+ result = join17(result, ["else ", this.generateStatement(stmt.alternate, bodyFlags)]);
60778
60778
  } else {
60779
- result = join16(result, join16("else", this.maybeBlock(stmt.alternate, bodyFlags)));
60779
+ result = join17(result, join17("else", this.maybeBlock(stmt.alternate, bodyFlags)));
60780
60780
  }
60781
60781
  } else {
60782
60782
  result.push(this.maybeBlock(stmt.consequent, bodyFlags));
@@ -60877,7 +60877,7 @@ var require_escodegen = __commonJS({
60877
60877
  },
60878
60878
  ReturnStatement: function(stmt, flags) {
60879
60879
  if (stmt.argument) {
60880
- return [join16(
60880
+ return [join17(
60881
60881
  "return",
60882
60882
  this.generateExpression(stmt.argument, Precedence.Sequence, E_TTT)
60883
60883
  ), this.semicolon(flags)];
@@ -60966,14 +60966,14 @@ var require_escodegen = __commonJS({
60966
60966
  if (leftSource.charCodeAt(leftSource.length - 1) === 47 && esutils.code.isIdentifierPartES5(expr.operator.charCodeAt(0))) {
60967
60967
  result = [fragment, noEmptySpace(), expr.operator];
60968
60968
  } else {
60969
- result = join16(fragment, expr.operator);
60969
+ result = join17(fragment, expr.operator);
60970
60970
  }
60971
60971
  fragment = this.generateExpression(expr.right, rightPrecedence, flags);
60972
60972
  if (expr.operator === "/" && fragment.toString().charAt(0) === "/" || expr.operator.slice(-1) === "<" && fragment.toString().slice(0, 3) === "!--") {
60973
60973
  result.push(noEmptySpace());
60974
60974
  result.push(fragment);
60975
60975
  } else {
60976
- result = join16(result, fragment);
60976
+ result = join17(result, fragment);
60977
60977
  }
60978
60978
  if (expr.operator === "in" && !(flags & F_ALLOW_IN)) {
60979
60979
  return ["(", result, ")"];
@@ -61013,7 +61013,7 @@ var require_escodegen = __commonJS({
61013
61013
  var result, length, i, iz, itemFlags;
61014
61014
  length = expr["arguments"].length;
61015
61015
  itemFlags = flags & F_ALLOW_UNPARATH_NEW && !parentheses && length === 0 ? E_TFT : E_TFF;
61016
- result = join16(
61016
+ result = join17(
61017
61017
  "new",
61018
61018
  this.generateExpression(expr.callee, Precedence.New, itemFlags)
61019
61019
  );
@@ -61063,11 +61063,11 @@ var require_escodegen = __commonJS({
61063
61063
  var result, fragment, rightCharCode, leftSource, leftCharCode;
61064
61064
  fragment = this.generateExpression(expr.argument, Precedence.Unary, E_TTT);
61065
61065
  if (space === "") {
61066
- result = join16(expr.operator, fragment);
61066
+ result = join17(expr.operator, fragment);
61067
61067
  } else {
61068
61068
  result = [expr.operator];
61069
61069
  if (expr.operator.length > 2) {
61070
- result = join16(result, fragment);
61070
+ result = join17(result, fragment);
61071
61071
  } else {
61072
61072
  leftSource = toSourceNodeWhenNeeded(result).toString();
61073
61073
  leftCharCode = leftSource.charCodeAt(leftSource.length - 1);
@@ -61090,7 +61090,7 @@ var require_escodegen = __commonJS({
61090
61090
  result = "yield";
61091
61091
  }
61092
61092
  if (expr.argument) {
61093
- result = join16(
61093
+ result = join17(
61094
61094
  result,
61095
61095
  this.generateExpression(expr.argument, Precedence.Yield, E_TTT)
61096
61096
  );
@@ -61098,7 +61098,7 @@ var require_escodegen = __commonJS({
61098
61098
  return parenthesize(result, Precedence.Yield, precedence);
61099
61099
  },
61100
61100
  AwaitExpression: function(expr, precedence, flags) {
61101
- var result = join16(
61101
+ var result = join17(
61102
61102
  expr.all ? "await*" : "await",
61103
61103
  this.generateExpression(expr.argument, Precedence.Await, E_TTT)
61104
61104
  );
@@ -61181,11 +61181,11 @@ var require_escodegen = __commonJS({
61181
61181
  var result, fragment;
61182
61182
  result = ["class"];
61183
61183
  if (expr.id) {
61184
- result = join16(result, this.generateExpression(expr.id, Precedence.Sequence, E_TTT));
61184
+ result = join17(result, this.generateExpression(expr.id, Precedence.Sequence, E_TTT));
61185
61185
  }
61186
61186
  if (expr.superClass) {
61187
- fragment = join16("extends", this.generateExpression(expr.superClass, Precedence.Unary, E_TTT));
61188
- result = join16(result, fragment);
61187
+ fragment = join17("extends", this.generateExpression(expr.superClass, Precedence.Unary, E_TTT));
61188
+ result = join17(result, fragment);
61189
61189
  }
61190
61190
  result.push(space);
61191
61191
  result.push(this.generateStatement(expr.body, S_TFFT));
@@ -61200,7 +61200,7 @@ var require_escodegen = __commonJS({
61200
61200
  }
61201
61201
  if (expr.kind === "get" || expr.kind === "set") {
61202
61202
  fragment = [
61203
- join16(expr.kind, this.generatePropertyKey(expr.key, expr.computed)),
61203
+ join17(expr.kind, this.generatePropertyKey(expr.key, expr.computed)),
61204
61204
  this.generateFunctionBody(expr.value)
61205
61205
  ];
61206
61206
  } else {
@@ -61210,7 +61210,7 @@ var require_escodegen = __commonJS({
61210
61210
  this.generateFunctionBody(expr.value)
61211
61211
  ];
61212
61212
  }
61213
- return join16(result, fragment);
61213
+ return join17(result, fragment);
61214
61214
  },
61215
61215
  Property: function(expr, precedence, flags) {
61216
61216
  if (expr.kind === "get" || expr.kind === "set") {
@@ -61405,7 +61405,7 @@ var require_escodegen = __commonJS({
61405
61405
  for (i = 0, iz = expr.blocks.length; i < iz; ++i) {
61406
61406
  fragment = that.generateExpression(expr.blocks[i], Precedence.Sequence, E_TTT);
61407
61407
  if (i > 0 || extra.moz.comprehensionExpressionStartsWithAssignment) {
61408
- result = join16(result, fragment);
61408
+ result = join17(result, fragment);
61409
61409
  } else {
61410
61410
  result.push(fragment);
61411
61411
  }
@@ -61413,13 +61413,13 @@ var require_escodegen = __commonJS({
61413
61413
  });
61414
61414
  }
61415
61415
  if (expr.filter) {
61416
- result = join16(result, "if" + space);
61416
+ result = join17(result, "if" + space);
61417
61417
  fragment = this.generateExpression(expr.filter, Precedence.Sequence, E_TTT);
61418
- result = join16(result, ["(", fragment, ")"]);
61418
+ result = join17(result, ["(", fragment, ")"]);
61419
61419
  }
61420
61420
  if (!extra.moz.comprehensionExpressionStartsWithAssignment) {
61421
61421
  fragment = this.generateExpression(expr.body, Precedence.Assignment, E_TTT);
61422
- result = join16(result, fragment);
61422
+ result = join17(result, fragment);
61423
61423
  }
61424
61424
  result.push(expr.type === Syntax.GeneratorExpression ? ")" : "]");
61425
61425
  return result;
@@ -61435,8 +61435,8 @@ var require_escodegen = __commonJS({
61435
61435
  } else {
61436
61436
  fragment = this.generateExpression(expr.left, Precedence.Call, E_TTT);
61437
61437
  }
61438
- fragment = join16(fragment, expr.of ? "of" : "in");
61439
- fragment = join16(fragment, this.generateExpression(expr.right, Precedence.Sequence, E_TTT));
61438
+ fragment = join17(fragment, expr.of ? "of" : "in");
61439
+ fragment = join17(fragment, this.generateExpression(expr.right, Precedence.Sequence, E_TTT));
61440
61440
  return ["for" + space + "(", fragment, ")"];
61441
61441
  },
61442
61442
  SpreadElement: function(expr, precedence, flags) {
@@ -67966,11 +67966,11 @@ function __metadata(metadataKey, metadataValue) {
67966
67966
  }
67967
67967
  function __awaiter2(thisArg, _arguments, P, generator) {
67968
67968
  function adopt(value) {
67969
- return value instanceof P ? value : new P(function(resolve12) {
67970
- resolve12(value);
67969
+ return value instanceof P ? value : new P(function(resolve13) {
67970
+ resolve13(value);
67971
67971
  });
67972
67972
  }
67973
- return new (P || (P = Promise))(function(resolve12, reject) {
67973
+ return new (P || (P = Promise))(function(resolve13, reject) {
67974
67974
  function fulfilled(value) {
67975
67975
  try {
67976
67976
  step(generator.next(value));
@@ -67986,7 +67986,7 @@ function __awaiter2(thisArg, _arguments, P, generator) {
67986
67986
  }
67987
67987
  }
67988
67988
  function step(result) {
67989
- result.done ? resolve12(result.value) : adopt(result.value).then(fulfilled, rejected);
67989
+ result.done ? resolve13(result.value) : adopt(result.value).then(fulfilled, rejected);
67990
67990
  }
67991
67991
  step((generator = generator.apply(thisArg, _arguments || [])).next());
67992
67992
  });
@@ -68177,14 +68177,14 @@ function __asyncValues2(o) {
68177
68177
  }, i);
68178
68178
  function verb(n) {
68179
68179
  i[n] = o[n] && function(v) {
68180
- return new Promise(function(resolve12, reject) {
68181
- v = o[n](v), settle(resolve12, reject, v.done, v.value);
68180
+ return new Promise(function(resolve13, reject) {
68181
+ v = o[n](v), settle(resolve13, reject, v.done, v.value);
68182
68182
  });
68183
68183
  };
68184
68184
  }
68185
- function settle(resolve12, reject, d, v) {
68185
+ function settle(resolve13, reject, d, v) {
68186
68186
  Promise.resolve(v).then(function(v2) {
68187
- resolve12({ value: v2, done: d });
68187
+ resolve13({ value: v2, done: d });
68188
68188
  }, reject);
68189
68189
  }
68190
68190
  }
@@ -71737,12 +71737,12 @@ var require_util3 = __commonJS({
71737
71737
  exports.isGMT = exports.dnsLookup = void 0;
71738
71738
  var dns_1 = __require("dns");
71739
71739
  function dnsLookup(host, opts) {
71740
- return new Promise((resolve12, reject) => {
71740
+ return new Promise((resolve13, reject) => {
71741
71741
  (0, dns_1.lookup)(host, opts, (err, res) => {
71742
71742
  if (err) {
71743
71743
  reject(err);
71744
71744
  } else {
71745
- resolve12(res);
71745
+ resolve13(res);
71746
71746
  }
71747
71747
  });
71748
71748
  });
@@ -72107,10 +72107,10 @@ var require_myIpAddress = __commonJS({
72107
72107
  var ip_1 = require_ip();
72108
72108
  var net_1 = __importDefault2(__require("net"));
72109
72109
  async function myIpAddress() {
72110
- return new Promise((resolve12, reject) => {
72110
+ return new Promise((resolve13, reject) => {
72111
72111
  const socket = net_1.default.connect({ host: "8.8.8.8", port: 53 });
72112
72112
  const onError = () => {
72113
- resolve12(ip_1.ip.address());
72113
+ resolve13(ip_1.ip.address());
72114
72114
  };
72115
72115
  socket.once("error", onError);
72116
72116
  socket.once("connect", () => {
@@ -72118,9 +72118,9 @@ var require_myIpAddress = __commonJS({
72118
72118
  const addr = socket.address();
72119
72119
  socket.destroy();
72120
72120
  if (typeof addr === "string") {
72121
- resolve12(addr);
72121
+ resolve13(addr);
72122
72122
  } else if (addr.address) {
72123
- resolve12(addr.address);
72123
+ resolve13(addr.address);
72124
72124
  } else {
72125
72125
  reject(new Error("Expected a `string`"));
72126
72126
  }
@@ -72698,8 +72698,8 @@ var require_deferred_promise = __commonJS({
72698
72698
  this.context = args.context;
72699
72699
  this.owner = args.context.runtime;
72700
72700
  this.handle = args.promiseHandle;
72701
- this.settled = new Promise((resolve12) => {
72702
- this.onSettled = resolve12;
72701
+ this.settled = new Promise((resolve13) => {
72702
+ this.onSettled = resolve13;
72703
72703
  });
72704
72704
  this.resolveHandle = args.resolveHandle;
72705
72705
  this.rejectHandle = args.rejectHandle;
@@ -73220,13 +73220,13 @@ var require_context = __commonJS({
73220
73220
  if (vmResolveResult.error) {
73221
73221
  return Promise.resolve(vmResolveResult);
73222
73222
  }
73223
- return new Promise((resolve12) => {
73223
+ return new Promise((resolve13) => {
73224
73224
  lifetime_1.Scope.withScope((scope) => {
73225
73225
  const resolveHandle = scope.manage(this.newFunction("resolve", (value) => {
73226
- resolve12({ value: value && value.dup() });
73226
+ resolve13({ value: value && value.dup() });
73227
73227
  }));
73228
73228
  const rejectHandle = scope.manage(this.newFunction("reject", (error) => {
73229
- resolve12({ error: error && error.dup() });
73229
+ resolve13({ error: error && error.dup() });
73230
73230
  }));
73231
73231
  const promiseHandle = scope.manage(vmResolveResult.value);
73232
73232
  const promiseThenHandle = scope.manage(this.getProp(promiseHandle, "then"));
@@ -75601,13 +75601,13 @@ import * as http from "node:http";
75601
75601
  import * as https from "node:https";
75602
75602
  import { URL as URL2, urlToHttpOptions } from "node:url";
75603
75603
  function headHttpRequest(url) {
75604
- return new Promise((resolve12) => {
75604
+ return new Promise((resolve13) => {
75605
75605
  const request3 = httpRequest(url, "HEAD", (response) => {
75606
75606
  response.resume();
75607
- resolve12(response.statusCode === 200);
75607
+ resolve13(response.statusCode === 200);
75608
75608
  }, false);
75609
75609
  request3.on("error", () => {
75610
- resolve12(false);
75610
+ resolve13(false);
75611
75611
  });
75612
75612
  });
75613
75613
  }
@@ -75635,7 +75635,7 @@ function httpRequest(url, method, response, keepAlive = true) {
75635
75635
  return request3;
75636
75636
  }
75637
75637
  function downloadFile(url, destinationPath, progressCallback) {
75638
- return new Promise((resolve12, reject) => {
75638
+ return new Promise((resolve13, reject) => {
75639
75639
  let downloadedBytes = 0;
75640
75640
  let totalBytes = 0;
75641
75641
  function onData(chunk) {
@@ -75651,7 +75651,7 @@ function downloadFile(url, destinationPath, progressCallback) {
75651
75651
  }
75652
75652
  const file = createWriteStream(destinationPath);
75653
75653
  file.on("close", () => {
75654
- return resolve12();
75654
+ return resolve13();
75655
75655
  });
75656
75656
  file.on("error", (error) => {
75657
75657
  return reject(error);
@@ -75676,7 +75676,7 @@ async function getJSON(url) {
75676
75676
  }
75677
75677
  }
75678
75678
  function getText3(url) {
75679
- return new Promise((resolve12, reject) => {
75679
+ return new Promise((resolve13, reject) => {
75680
75680
  const request3 = httpRequest(url, "GET", (response) => {
75681
75681
  let data = "";
75682
75682
  if (response.statusCode && response.statusCode >= 400) {
@@ -75687,7 +75687,7 @@ function getText3(url) {
75687
75687
  });
75688
75688
  response.on("end", () => {
75689
75689
  try {
75690
- return resolve12(String(data));
75690
+ return resolve13(String(data));
75691
75691
  } catch {
75692
75692
  return reject(new Error(`Failed to read text response from ${url}`));
75693
75693
  }
@@ -77079,7 +77079,7 @@ var init_launch = __esm({
77079
77079
  if (opts.onExit) {
77080
77080
  this.#onExitHook = opts.onExit;
77081
77081
  }
77082
- this.#browserProcessExiting = new Promise((resolve12, reject) => {
77082
+ this.#browserProcessExiting = new Promise((resolve13, reject) => {
77083
77083
  this.#browserProcess.once("exit", async () => {
77084
77084
  debugLaunch(`Browser process ${this.#browserProcess.pid} onExit`);
77085
77085
  this.#clearListeners();
@@ -77090,7 +77090,7 @@ var init_launch = __esm({
77090
77090
  reject(err);
77091
77091
  return;
77092
77092
  }
77093
- resolve12();
77093
+ resolve13();
77094
77094
  });
77095
77095
  });
77096
77096
  }
@@ -77206,7 +77206,7 @@ Error cause: ${isErrorLike2(error) ? error.stack : error}`);
77206
77206
  return [...this.#logs];
77207
77207
  }
77208
77208
  waitForLineOutput(regex, timeout2 = 0) {
77209
- return new Promise((resolve12, reject) => {
77209
+ return new Promise((resolve13, reject) => {
77210
77210
  const onClose = (errorOrCode) => {
77211
77211
  cleanup();
77212
77212
  reject(new Error([
@@ -77242,7 +77242,7 @@ Error cause: ${isErrorLike2(error) ? error.stack : error}`);
77242
77242
  return;
77243
77243
  }
77244
77244
  cleanup();
77245
- resolve12(match2[1]);
77245
+ resolve13(match2[1]);
77246
77246
  }
77247
77247
  });
77248
77248
  }
@@ -77711,7 +77711,7 @@ var require_get_stream = __commonJS({
77711
77711
  };
77712
77712
  const { maxBuffer } = options;
77713
77713
  let stream2;
77714
- await new Promise((resolve12, reject) => {
77714
+ await new Promise((resolve13, reject) => {
77715
77715
  const rejectPromise = (error) => {
77716
77716
  if (error && stream2.getBufferedLength() <= BufferConstants.MAX_LENGTH) {
77717
77717
  error.bufferedData = stream2.getBufferedValue();
@@ -77723,7 +77723,7 @@ var require_get_stream = __commonJS({
77723
77723
  rejectPromise(error);
77724
77724
  return;
77725
77725
  }
77726
- resolve12();
77726
+ resolve13();
77727
77727
  });
77728
77728
  stream2.on("data", () => {
77729
77729
  if (stream2.getBufferedLength() > maxBuffer) {
@@ -79012,7 +79012,7 @@ var require_extract_zip = __commonJS({
79012
79012
  debug6("opening", this.zipPath, "with opts", this.opts);
79013
79013
  this.zipfile = await openZip(this.zipPath, { lazyEntries: true });
79014
79014
  this.canceled = false;
79015
- return new Promise((resolve12, reject) => {
79015
+ return new Promise((resolve13, reject) => {
79016
79016
  this.zipfile.on("error", (err) => {
79017
79017
  this.canceled = true;
79018
79018
  reject(err);
@@ -79021,7 +79021,7 @@ var require_extract_zip = __commonJS({
79021
79021
  this.zipfile.on("close", () => {
79022
79022
  if (!this.canceled) {
79023
79023
  debug6("zip extraction complete");
79024
- resolve12();
79024
+ resolve13();
79025
79025
  }
79026
79026
  });
79027
79027
  this.zipfile.on("entry", async (entry) => {
@@ -80278,8 +80278,8 @@ var require_streamx = __commonJS({
80278
80278
  return this;
80279
80279
  },
80280
80280
  next() {
80281
- return new Promise(function(resolve12, reject) {
80282
- promiseResolve = resolve12;
80281
+ return new Promise(function(resolve13, reject) {
80282
+ promiseResolve = resolve13;
80283
80283
  promiseReject = reject;
80284
80284
  const data = stream2.read();
80285
80285
  if (data !== null) ondata(data);
@@ -80309,11 +80309,11 @@ var require_streamx = __commonJS({
80309
80309
  }
80310
80310
  function destroy(err) {
80311
80311
  stream2.destroy(err);
80312
- return new Promise((resolve12, reject) => {
80313
- if (stream2._duplexState & DESTROYED) return resolve12({ value: void 0, done: true });
80312
+ return new Promise((resolve13, reject) => {
80313
+ if (stream2._duplexState & DESTROYED) return resolve13({ value: void 0, done: true });
80314
80314
  stream2.once("close", function() {
80315
80315
  if (err) reject(err);
80316
- else resolve12({ value: void 0, done: true });
80316
+ else resolve13({ value: void 0, done: true });
80317
80317
  });
80318
80318
  });
80319
80319
  }
@@ -80357,8 +80357,8 @@ var require_streamx = __commonJS({
80357
80357
  const writes = pending + (ws._duplexState & WRITE_WRITING ? 1 : 0);
80358
80358
  if (writes === 0) return Promise.resolve(true);
80359
80359
  if (state.drains === null) state.drains = [];
80360
- return new Promise((resolve12) => {
80361
- state.drains.push({ writes, resolve: resolve12 });
80360
+ return new Promise((resolve13) => {
80361
+ state.drains.push({ writes, resolve: resolve13 });
80362
80362
  });
80363
80363
  }
80364
80364
  write(data) {
@@ -80463,10 +80463,10 @@ var require_streamx = __commonJS({
80463
80463
  cb(null);
80464
80464
  }
80465
80465
  function pipelinePromise(...streams) {
80466
- return new Promise((resolve12, reject) => {
80466
+ return new Promise((resolve13, reject) => {
80467
80467
  return pipeline(...streams, (err) => {
80468
80468
  if (err) return reject(err);
80469
- resolve12();
80469
+ resolve13();
80470
80470
  });
80471
80471
  });
80472
80472
  }
@@ -81121,16 +81121,16 @@ var require_extract = __commonJS({
81121
81121
  entryCallback = null;
81122
81122
  cb(err);
81123
81123
  }
81124
- function onnext(resolve12, reject) {
81124
+ function onnext(resolve13, reject) {
81125
81125
  if (error) {
81126
81126
  return reject(error);
81127
81127
  }
81128
81128
  if (entryStream) {
81129
- resolve12({ value: entryStream, done: false });
81129
+ resolve13({ value: entryStream, done: false });
81130
81130
  entryStream = null;
81131
81131
  return;
81132
81132
  }
81133
- promiseResolve = resolve12;
81133
+ promiseResolve = resolve13;
81134
81134
  promiseReject = reject;
81135
81135
  consumeCallback(null);
81136
81136
  if (extract._finished && promiseResolve) {
@@ -81158,11 +81158,11 @@ var require_extract = __commonJS({
81158
81158
  function destroy(err) {
81159
81159
  extract.destroy(err);
81160
81160
  consumeCallback(err);
81161
- return new Promise((resolve12, reject) => {
81162
- if (extract.destroyed) return resolve12({ value: void 0, done: true });
81161
+ return new Promise((resolve13, reject) => {
81162
+ if (extract.destroyed) return resolve13({ value: void 0, done: true });
81163
81163
  extract.once("close", function() {
81164
81164
  if (err) reject(err);
81165
- else resolve12({ value: void 0, done: true });
81165
+ else resolve13({ value: void 0, done: true });
81166
81166
  });
81167
81167
  });
81168
81168
  }
@@ -86138,12 +86138,12 @@ var init_yargs_factory = __esm({
86138
86138
  async getCompletion(args, done) {
86139
86139
  argsert("<array> [function]", [args, done], arguments.length);
86140
86140
  if (!done) {
86141
- return new Promise((resolve12, reject) => {
86141
+ return new Promise((resolve13, reject) => {
86142
86142
  __classPrivateFieldGet2(this, _YargsInstance_completion, "f").getCompletion(args, (err, completions) => {
86143
86143
  if (err)
86144
86144
  reject(err);
86145
86145
  else
86146
- resolve12(completions);
86146
+ resolve13(completions);
86147
86147
  });
86148
86148
  });
86149
86149
  } else {
@@ -87598,9 +87598,9 @@ async function getConnectionTransport(options) {
87598
87598
  throw new Error("Could not detect required browser platform");
87599
87599
  }
87600
87600
  const { convertPuppeteerChannelToBrowsersChannel: convertPuppeteerChannelToBrowsersChannel2 } = await Promise.resolve().then(() => (init_LaunchOptions(), LaunchOptions_exports));
87601
- const { join: join16 } = await import("node:path");
87601
+ const { join: join17 } = await import("node:path");
87602
87602
  const userDataDir = resolveDefaultUserDataDir3(Browser4.CHROME, platform, convertPuppeteerChannelToBrowsersChannel2(options.channel));
87603
- const portPath = join16(userDataDir, "DevToolsActivePort");
87603
+ const portPath = join17(userDataDir, "DevToolsActivePort");
87604
87604
  try {
87605
87605
  const fileContent = await environment.value.fs.promises.readFile(portPath, "ascii");
87606
87606
  const [rawPort, rawPath] = fileContent.split("\n").map((line) => {
@@ -88944,8 +88944,8 @@ var init_ScreenRecorder = __esm({
88944
88944
  static {
88945
88945
  const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
88946
88946
  __esDecorate23(this, _private_writeFrame_descriptor = { value: __setFunctionName6(async function(buffer) {
88947
- const error = await new Promise((resolve12) => {
88948
- this.#process.stdin.write(buffer, resolve12);
88947
+ const error = await new Promise((resolve13) => {
88948
+ this.#process.stdin.write(buffer, resolve13);
88949
88949
  });
88950
88950
  if (error) {
88951
88951
  console.log(`ffmpeg failed to write: ${error.message}.`);
@@ -89135,8 +89135,8 @@ var init_ScreenRecorder = __esm({
89135
89135
  const [buffer, timestamp] = await this.#lastFrame;
89136
89136
  await Promise.all(Array(Math.max(1, Math.round(this.#fps * (performance.now() - timestamp) / 1e3))).fill(buffer).map(this.#writeFrame.bind(this)));
89137
89137
  this.#process.stdin.end();
89138
- await new Promise((resolve12) => {
89139
- this.#process.once("close", resolve12);
89138
+ await new Promise((resolve13) => {
89139
+ this.#process.once("close", resolve13);
89140
89140
  });
89141
89141
  }
89142
89142
  /**
@@ -89426,7 +89426,7 @@ import {
89426
89426
  rmSync as rmSync4,
89427
89427
  createReadStream as createReadStream2
89428
89428
  } from "node:fs";
89429
- import { resolve as resolve11, dirname as dirname10, join as join15 } from "node:path";
89429
+ import { resolve as resolve12, dirname as dirname11, join as join16 } from "node:path";
89430
89430
  import { tmpdir as tmpdir2 } from "node:os";
89431
89431
  import { parseArgs } from "node:util";
89432
89432
  import crypto2 from "node:crypto";
@@ -92061,7 +92061,7 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
92061
92061
  });
92062
92062
  if (!chunk) {
92063
92063
  if (i === 1) {
92064
- await new Promise((resolve12) => setTimeout(resolve12));
92064
+ await new Promise((resolve13) => setTimeout(resolve13));
92065
92065
  maxReadCount = 3;
92066
92066
  continue;
92067
92067
  }
@@ -95821,8 +95821,8 @@ var CustomElementRegistry = class {
95821
95821
  } : (element) => element.localName === localName;
95822
95822
  registry.set(localName, { Class, check });
95823
95823
  if (waiting.has(localName)) {
95824
- for (const resolve12 of waiting.get(localName))
95825
- resolve12(Class);
95824
+ for (const resolve13 of waiting.get(localName))
95825
+ resolve13(Class);
95826
95826
  waiting.delete(localName);
95827
95827
  }
95828
95828
  ownerDocument.querySelectorAll(
@@ -95862,13 +95862,13 @@ var CustomElementRegistry = class {
95862
95862
  */
95863
95863
  whenDefined(localName) {
95864
95864
  const { registry, waiting } = this;
95865
- return new Promise((resolve12) => {
95865
+ return new Promise((resolve13) => {
95866
95866
  if (registry.has(localName))
95867
- resolve12(registry.get(localName).Class);
95867
+ resolve13(registry.get(localName).Class);
95868
95868
  else {
95869
95869
  if (!waiting.has(localName))
95870
95870
  waiting.set(localName, []);
95871
- waiting.get(localName).push(resolve12);
95871
+ waiting.get(localName).push(resolve13);
95872
95872
  }
95873
95873
  });
95874
95874
  }
@@ -101696,7 +101696,7 @@ function buildChromeArgs(options, config2) {
101696
101696
 
101697
101697
  // ../engine/src/services/frameCapture.ts
101698
101698
  import { existsSync as existsSync4, mkdirSync, writeFileSync } from "fs";
101699
- import { join as join4 } from "path";
101699
+ import { join as join5 } from "path";
101700
101700
 
101701
101701
  // ../core/src/parsers/gsapParser.ts
101702
101702
  var GSAP_METHODS = /* @__PURE__ */ new Set(["set", "to", "from", "fromTo"]);
@@ -101971,80 +101971,175 @@ function clampDurations(html, clamps) {
101971
101971
  return html;
101972
101972
  }
101973
101973
 
101974
- // ../core/src/lint/hyperframeLinter.ts
101974
+ // ../core/src/lint/utils.ts
101975
101975
  var TAG_PATTERN = /<([a-z][\w:-]*)(\s[^<>]*?)?>/gi;
101976
101976
  var STYLE_BLOCK_PATTERN = /<style\b([^>]*)>([\s\S]*?)<\/style>/gi;
101977
101977
  var SCRIPT_BLOCK_PATTERN = /<script\b([^>]*)>([\s\S]*?)<\/script>/gi;
101978
101978
  var COMPOSITION_ID_IN_CSS_PATTERN = /\[data-composition-id=["']([^"']+)["']\]/g;
101979
101979
  var TIMELINE_REGISTRY_INIT_PATTERN = /window\.__timelines\s*=\s*window\.__timelines\s*\|\|\s*\{\}|window\.__timelines\s*=\s*\{\}|window\.__timelines\s*\?\?=\s*\{\}/i;
101980
101980
  var TIMELINE_REGISTRY_ASSIGN_PATTERN = /window\.__timelines\[[^\]]+\]\s*=/i;
101981
- var INVALID_SCRIPT_CLOSE_PATTERN = /<script[^>]*>[\s\S]*?<\s*\/\s*script(?!>)/i;
101982
101981
  var WINDOW_TIMELINE_ASSIGN_PATTERN = /window\.__timelines\[\s*["']([^"']+)["']\s*\]\s*=\s*([A-Za-z_$][\w$]*)/i;
101983
- var META_GSAP_KEYS = /* @__PURE__ */ new Set(["duration", "ease", "repeat", "yoyo", "overwrite", "delay"]);
101984
- function lintHyperframeHtml(html, options = {}) {
101982
+ var INVALID_SCRIPT_CLOSE_PATTERN = /<script[^>]*>[\s\S]*?<\s*\/\s*script(?!>)/i;
101983
+ function extractOpenTags(source2) {
101984
+ const tags = [];
101985
+ let match2;
101986
+ const pattern = new RegExp(TAG_PATTERN.source, TAG_PATTERN.flags);
101987
+ while ((match2 = pattern.exec(source2)) !== null) {
101988
+ const raw2 = match2[0];
101989
+ if (raw2.startsWith("</") || raw2.startsWith("<!")) continue;
101990
+ tags.push({
101991
+ raw: raw2,
101992
+ name: (match2[1] || "").toLowerCase(),
101993
+ attrs: match2[2] || "",
101994
+ index: match2.index
101995
+ });
101996
+ }
101997
+ return tags;
101998
+ }
101999
+ function extractBlocks(source2, pattern) {
102000
+ const blocks = [];
102001
+ let match2;
102002
+ const p = new RegExp(pattern.source, pattern.flags);
102003
+ while ((match2 = p.exec(source2)) !== null) {
102004
+ blocks.push({
102005
+ attrs: match2[1] || "",
102006
+ content: match2[2] || "",
102007
+ raw: match2[0],
102008
+ index: match2.index
102009
+ });
102010
+ }
102011
+ return blocks;
102012
+ }
102013
+ function findRootTag(source2) {
102014
+ const bodyMatch = source2.match(/<body\b[^>]*>([\s\S]*?)<\/body>/i);
102015
+ const bodyContent = bodyMatch ? bodyMatch[1] ?? source2 : source2;
102016
+ const bodyTags = extractOpenTags(bodyContent);
102017
+ for (const tag of bodyTags) {
102018
+ if (["script", "style", "meta", "link", "title"].includes(tag.name)) continue;
102019
+ return tag;
102020
+ }
102021
+ return null;
102022
+ }
102023
+ function readAttr(tagSource, attr) {
102024
+ if (!tagSource) return null;
102025
+ const escaped = attr.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
102026
+ const match2 = tagSource.match(new RegExp(`\\b${escaped}\\s*=\\s*["']([^"']+)["']`, "i"));
102027
+ return match2?.[1] || null;
102028
+ }
102029
+ function collectCompositionIds(tags) {
102030
+ const ids = /* @__PURE__ */ new Set();
102031
+ for (const tag of tags) {
102032
+ const compId = readAttr(tag.raw, "data-composition-id");
102033
+ if (compId) ids.add(compId);
102034
+ }
102035
+ return ids;
102036
+ }
102037
+ function extractCompositionIdsFromCss(css) {
102038
+ const ids = /* @__PURE__ */ new Set();
102039
+ let match2;
102040
+ const pattern = new RegExp(
102041
+ COMPOSITION_ID_IN_CSS_PATTERN.source,
102042
+ COMPOSITION_ID_IN_CSS_PATTERN.flags
102043
+ );
102044
+ while ((match2 = pattern.exec(css)) !== null) {
102045
+ if (match2[1]) ids.add(match2[1]);
102046
+ }
102047
+ return [...ids];
102048
+ }
102049
+ function getInlineScriptSyntaxError(source2) {
102050
+ if (!source2.trim()) return null;
102051
+ try {
102052
+ new Function(source2);
102053
+ return null;
102054
+ } catch (error) {
102055
+ if (error instanceof Error) return error.message;
102056
+ return String(error);
102057
+ }
102058
+ }
102059
+ function isMediaTag(tagName19) {
102060
+ return tagName19 === "video" || tagName19 === "audio" || tagName19 === "img";
102061
+ }
102062
+ function truncateSnippet(value, maxLength = 220) {
102063
+ const normalized = value.replace(/\s+/g, " ").trim();
102064
+ if (!normalized) return void 0;
102065
+ if (normalized.length <= maxLength) return normalized;
102066
+ return `${normalized.slice(0, maxLength - 3)}...`;
102067
+ }
102068
+
102069
+ // ../core/src/lint/context.ts
102070
+ function buildLintContext(html, options = {}) {
101985
102071
  let source2 = html || "";
101986
102072
  const templateMatch = source2.match(/<template[^>]*>([\s\S]*)<\/template>/i);
101987
102073
  if (templateMatch?.[1]) source2 = templateMatch[1];
101988
- const filePath = options.filePath;
101989
- const findings = [];
101990
- const seen = /* @__PURE__ */ new Set();
101991
- const pushFinding = (finding) => {
101992
- const dedupeKey = [
101993
- finding.code,
101994
- finding.severity,
101995
- finding.selector || "",
101996
- finding.elementId || "",
101997
- finding.message
101998
- ].join("|");
101999
- if (seen.has(dedupeKey)) {
102000
- return;
102001
- }
102002
- seen.add(dedupeKey);
102003
- findings.push(filePath ? { ...finding, file: filePath } : finding);
102004
- };
102005
102074
  const tags = extractOpenTags(source2);
102006
102075
  const styles = extractBlocks(source2, STYLE_BLOCK_PATTERN);
102007
102076
  const scripts = extractBlocks(source2, SCRIPT_BLOCK_PATTERN);
102008
102077
  const compositionIds = collectCompositionIds(tags);
102009
102078
  const rootTag = findRootTag(source2);
102010
102079
  const rootCompositionId = readAttr(rootTag?.raw || "", "data-composition-id");
102011
- if (!rootTag || !readAttr(rootTag.raw, "data-composition-id")) {
102012
- pushFinding({
102013
- code: "root_missing_composition_id",
102014
- severity: "error",
102015
- message: "Root composition is missing `data-composition-id`.",
102016
- elementId: rootTag ? readAttr(rootTag.raw, "id") || void 0 : void 0,
102017
- fixHint: "Add a stable `data-composition-id` to the entry composition wrapper.",
102018
- snippet: truncateSnippet(rootTag?.raw || "")
102019
- });
102020
- }
102021
- if (!rootTag || !readAttr(rootTag.raw, "data-width") || !readAttr(rootTag.raw, "data-height")) {
102022
- pushFinding({
102023
- code: "root_missing_dimensions",
102024
- severity: "error",
102025
- message: "Root composition is missing `data-width` or `data-height`.",
102026
- elementId: rootTag ? readAttr(rootTag.raw, "id") || void 0 : void 0,
102027
- fixHint: "Set numeric `data-width` and `data-height` on the entry composition root.",
102028
- snippet: truncateSnippet(rootTag?.raw || "")
102029
- });
102030
- }
102031
- if (!TIMELINE_REGISTRY_INIT_PATTERN.test(source2) && !TIMELINE_REGISTRY_ASSIGN_PATTERN.test(source2)) {
102032
- pushFinding({
102033
- code: "missing_timeline_registry",
102034
- severity: "error",
102035
- message: "Missing `window.__timelines` registration.",
102036
- fixHint: "Register each composition timeline on `window.__timelines[compositionId]`."
102037
- });
102038
- }
102039
- if (TIMELINE_REGISTRY_ASSIGN_PATTERN.test(source2) && !TIMELINE_REGISTRY_INIT_PATTERN.test(source2)) {
102040
- pushFinding({
102041
- code: "timeline_registry_missing_init",
102042
- severity: "error",
102043
- message: "`window.__timelines[\u2026] = \u2026` is used without initializing `window.__timelines` first.",
102044
- fixHint: "Add `window.__timelines = window.__timelines || {};` before any timeline assignment."
102045
- });
102046
- }
102047
- {
102080
+ return {
102081
+ source: source2,
102082
+ tags,
102083
+ styles,
102084
+ scripts,
102085
+ compositionIds,
102086
+ rootTag,
102087
+ rootCompositionId,
102088
+ options
102089
+ };
102090
+ }
102091
+
102092
+ // ../core/src/lint/rules/core.ts
102093
+ var coreRules = [
102094
+ // root_missing_composition_id + root_missing_dimensions
102095
+ ({ rootTag }) => {
102096
+ const findings = [];
102097
+ if (!rootTag || !readAttr(rootTag.raw, "data-composition-id")) {
102098
+ findings.push({
102099
+ code: "root_missing_composition_id",
102100
+ severity: "error",
102101
+ message: "Root composition is missing `data-composition-id`.",
102102
+ elementId: rootTag ? readAttr(rootTag.raw, "id") || void 0 : void 0,
102103
+ fixHint: "Add a stable `data-composition-id` to the entry composition wrapper.",
102104
+ snippet: truncateSnippet(rootTag?.raw || "")
102105
+ });
102106
+ }
102107
+ if (!rootTag || !readAttr(rootTag.raw, "data-width") || !readAttr(rootTag.raw, "data-height")) {
102108
+ findings.push({
102109
+ code: "root_missing_dimensions",
102110
+ severity: "error",
102111
+ message: "Root composition is missing `data-width` or `data-height`.",
102112
+ elementId: rootTag ? readAttr(rootTag.raw, "id") || void 0 : void 0,
102113
+ fixHint: "Set numeric `data-width` and `data-height` on the entry composition root.",
102114
+ snippet: truncateSnippet(rootTag?.raw || "")
102115
+ });
102116
+ }
102117
+ return findings;
102118
+ },
102119
+ // missing_timeline_registry + timeline_registry_missing_init
102120
+ ({ source: source2 }) => {
102121
+ const findings = [];
102122
+ if (!TIMELINE_REGISTRY_INIT_PATTERN.test(source2) && !TIMELINE_REGISTRY_ASSIGN_PATTERN.test(source2)) {
102123
+ findings.push({
102124
+ code: "missing_timeline_registry",
102125
+ severity: "error",
102126
+ message: "Missing `window.__timelines` registration.",
102127
+ fixHint: "Register each composition timeline on `window.__timelines[compositionId]`."
102128
+ });
102129
+ }
102130
+ if (TIMELINE_REGISTRY_ASSIGN_PATTERN.test(source2) && !TIMELINE_REGISTRY_INIT_PATTERN.test(source2)) {
102131
+ findings.push({
102132
+ code: "timeline_registry_missing_init",
102133
+ severity: "error",
102134
+ message: "`window.__timelines[\u2026] = \u2026` is used without initializing `window.__timelines` first.",
102135
+ fixHint: "Add `window.__timelines = window.__timelines || {};` before any timeline assignment."
102136
+ });
102137
+ }
102138
+ return findings;
102139
+ },
102140
+ // timeline_id_mismatch
102141
+ ({ source: source2 }) => {
102142
+ const findings = [];
102048
102143
  const htmlCompIds = /* @__PURE__ */ new Set();
102049
102144
  const timelineRegKeys = /* @__PURE__ */ new Set();
102050
102145
  const compIdRe = /data-composition-id\s*=\s*["']([^"']+)["']/gi;
@@ -102058,7 +102153,7 @@ function lintHyperframeHtml(html, options = {}) {
102058
102153
  }
102059
102154
  for (const key2 of timelineRegKeys) {
102060
102155
  if (!htmlCompIds.has(key2)) {
102061
- pushFinding({
102156
+ findings.push({
102062
102157
  code: "timeline_id_mismatch",
102063
102158
  severity: "error",
102064
102159
  message: `Timeline registered as "${key2}" but no element has data-composition-id="${key2}". The runtime cannot auto-nest this timeline.`,
@@ -102066,261 +102161,194 @@ function lintHyperframeHtml(html, options = {}) {
102066
102161
  });
102067
102162
  }
102068
102163
  }
102069
- }
102070
- if (INVALID_SCRIPT_CLOSE_PATTERN.test(source2)) {
102071
- pushFinding({
102072
- code: "invalid_inline_script_syntax",
102073
- severity: "error",
102074
- message: "Detected malformed inline `<script>` closing syntax.",
102075
- fixHint: "Close inline scripts with a valid `</script>` tag."
102076
- });
102077
- }
102078
- for (const script of scripts) {
102079
- const attrs = script.attrs || "";
102080
- if (/\bsrc\s*=/.test(attrs) || /\btype\s*=\s*["']application\/json["']/.test(attrs)) {
102081
- continue;
102082
- }
102083
- const syntaxError = getInlineScriptSyntaxError(script.content);
102084
- if (!syntaxError) {
102085
- continue;
102086
- }
102087
- pushFinding({
102088
- code: "invalid_inline_script_syntax",
102089
- severity: "error",
102090
- message: `Inline script has invalid syntax: ${syntaxError}`,
102091
- fixHint: "Fix the inline script syntax before render verification.",
102092
- snippet: truncateSnippet(script.content)
102093
- });
102094
- }
102095
- for (const tag of tags) {
102096
- const src = readAttr(tag.raw, "data-composition-src");
102097
- if (!src) {
102098
- continue;
102099
- }
102100
- const compId = readAttr(tag.raw, "data-composition-id");
102101
- if (compId) {
102102
- continue;
102103
- }
102104
- pushFinding({
102105
- code: "host_missing_composition_id",
102106
- severity: "error",
102107
- message: `Composition host for "${src}" is missing \`data-composition-id\`.`,
102108
- elementId: readAttr(tag.raw, "id") || void 0,
102109
- fixHint: "Set `data-composition-id` on every `data-composition-src` host element.",
102110
- snippet: truncateSnippet(tag.raw)
102111
- });
102112
- }
102113
- const scopedCssCompositionIds = /* @__PURE__ */ new Set();
102114
- for (const style of styles) {
102115
- for (const compId of extractCompositionIdsFromCss(style.content)) {
102116
- scopedCssCompositionIds.add(compId);
102117
- }
102118
- }
102119
- for (const compId of scopedCssCompositionIds) {
102120
- if (compositionIds.has(compId)) {
102121
- continue;
102122
- }
102123
- pushFinding({
102124
- code: "scoped_css_missing_wrapper",
102125
- severity: "warning",
102126
- message: `Scoped CSS targets composition "${compId}" but no matching wrapper exists in this HTML.`,
102127
- selector: `[data-composition-id="${compId}"]`,
102128
- fixHint: "Preserve the matching composition wrapper or align the CSS scope to an existing wrapper."
102129
- });
102130
- }
102131
- const mediaById = /* @__PURE__ */ new Map();
102132
- const mediaFingerprintCounts = /* @__PURE__ */ new Map();
102133
- for (const tag of tags) {
102134
- if (!isMediaTag(tag.name)) {
102135
- continue;
102136
- }
102137
- const elementId = readAttr(tag.raw, "id");
102138
- if (elementId) {
102139
- const existing = mediaById.get(elementId) || [];
102140
- existing.push(tag);
102141
- mediaById.set(elementId, existing);
102142
- }
102143
- const fingerprint = [
102144
- tag.name,
102145
- readAttr(tag.raw, "src") || "",
102146
- readAttr(tag.raw, "data-start") || "",
102147
- readAttr(tag.raw, "data-duration") || ""
102148
- ].join("|");
102149
- mediaFingerprintCounts.set(fingerprint, (mediaFingerprintCounts.get(fingerprint) || 0) + 1);
102150
- }
102151
- for (const [elementId, mediaTags] of mediaById) {
102152
- if (mediaTags.length < 2) {
102153
- continue;
102154
- }
102155
- pushFinding({
102156
- code: "duplicate_media_id",
102157
- severity: "error",
102158
- message: `Media id "${elementId}" is defined multiple times.`,
102159
- elementId,
102160
- fixHint: "Give each media element a unique id so preview and producer discover the same media graph.",
102161
- snippet: truncateSnippet(mediaTags[0]?.raw || "")
102162
- });
102163
- }
102164
- for (const [fingerprint, count] of mediaFingerprintCounts) {
102165
- if (count < 2) {
102166
- continue;
102167
- }
102168
- const [tagName19, src, dataStart, dataDuration] = fingerprint.split("|");
102169
- pushFinding({
102170
- code: "duplicate_media_discovery_risk",
102171
- severity: "warning",
102172
- message: `Detected ${count} matching ${tagName19} entries with the same source/start/duration.`,
102173
- fixHint: "Avoid duplicated media nodes that can be discovered twice during compilation.",
102174
- snippet: truncateSnippet(
102175
- `${tagName19} src=${src} data-start=${dataStart} data-duration=${dataDuration}`
102176
- )
102177
- });
102178
- }
102179
- const clipIds = /* @__PURE__ */ new Map();
102180
- const clipClasses = /* @__PURE__ */ new Map();
102181
- for (const tag of tags) {
102182
- const classAttr = readAttr(tag.raw, "class") || "";
102183
- const classes = classAttr.split(/\s+/).filter(Boolean);
102184
- if (!classes.includes("clip")) continue;
102185
- const id = readAttr(tag.raw, "id");
102186
- const info = { tag: tag.name, id: id || "", classes: classAttr };
102187
- if (id) clipIds.set(`#${id}`, info);
102188
- for (const cls of classes) {
102189
- if (cls !== "clip") clipClasses.set(`.${cls}`, info);
102190
- }
102191
- }
102192
- const classUsage = countClassUsage(tags);
102193
- for (const script of scripts) {
102194
- const localTimelineCompId = readRegisteredTimelineCompositionId(script.content);
102195
- const gsapWindows = extractGsapWindows(script.content);
102196
- for (let i = 0; i < gsapWindows.length; i++) {
102197
- const left2 = gsapWindows[i];
102198
- if (!left2) continue;
102199
- if (left2.end <= left2.position) {
102200
- continue;
102201
- }
102202
- for (let j = i + 1; j < gsapWindows.length; j++) {
102203
- const right2 = gsapWindows[j];
102204
- if (!right2) continue;
102205
- if (right2.end <= right2.position) {
102206
- continue;
102207
- }
102208
- if (left2.targetSelector !== right2.targetSelector) {
102209
- continue;
102210
- }
102211
- const overlapStart = Math.max(left2.position, right2.position);
102212
- const overlapEnd = Math.min(left2.end, right2.end);
102213
- if (overlapEnd <= overlapStart) {
102214
- continue;
102215
- }
102216
- if (left2.overwriteAuto || right2.overwriteAuto) {
102217
- continue;
102218
- }
102219
- const sharedProperties = left2.properties.filter((prop2) => right2.properties.includes(prop2));
102220
- if (sharedProperties.length === 0) {
102221
- continue;
102222
- }
102223
- pushFinding({
102224
- code: "overlapping_gsap_tweens",
102225
- severity: "warning",
102226
- message: `GSAP tweens overlap on "${left2.targetSelector}" for ${sharedProperties.join(", ")} between ${overlapStart.toFixed(2)}s and ${overlapEnd.toFixed(2)}s.`,
102227
- selector: left2.targetSelector,
102228
- fixHint: 'Shorten the earlier tween, move the later tween, or add `overwrite: "auto"`.',
102229
- snippet: truncateSnippet(`${left2.raw}
102230
- ${right2.raw}`)
102231
- });
102164
+ return findings;
102165
+ },
102166
+ // invalid_inline_script_syntax (malformed close tag)
102167
+ ({ source: source2 }) => {
102168
+ if (!INVALID_SCRIPT_CLOSE_PATTERN.test(source2)) return [];
102169
+ return [
102170
+ {
102171
+ code: "invalid_inline_script_syntax",
102172
+ severity: "error",
102173
+ message: "Detected malformed inline `<script>` closing syntax.",
102174
+ fixHint: "Close inline scripts with a valid `</script>` tag."
102232
102175
  }
102233
- }
102234
- for (const win of gsapWindows) {
102235
- const sel = win.targetSelector;
102236
- const clipInfo = clipIds.get(sel) || clipClasses.get(sel);
102237
- if (!clipInfo) continue;
102238
- const elDesc = `<${clipInfo.tag}${clipInfo.id ? ` id="${clipInfo.id}"` : ""} class="${clipInfo.classes}">`;
102239
- pushFinding({
102240
- code: "gsap_animates_clip_element",
102176
+ ];
102177
+ },
102178
+ // invalid_inline_script_syntax (JS parse error)
102179
+ ({ scripts }) => {
102180
+ const findings = [];
102181
+ for (const script of scripts) {
102182
+ const attrs = script.attrs || "";
102183
+ if (/\bsrc\s*=/.test(attrs) || /\btype\s*=\s*["']application\/json["']/.test(attrs)) continue;
102184
+ const syntaxError = getInlineScriptSyntaxError(script.content);
102185
+ if (!syntaxError) continue;
102186
+ findings.push({
102187
+ code: "invalid_inline_script_syntax",
102241
102188
  severity: "error",
102242
- message: `GSAP animation targets a clip element. Selector "${sel}" resolves to element ${elDesc}. The framework manages clip visibility \u2014 animate an inner wrapper instead.`,
102243
- selector: sel,
102244
- elementId: clipInfo.id || void 0,
102245
- fixHint: "Wrap content in a child <div> and target that with GSAP.",
102246
- snippet: truncateSnippet(win.raw)
102189
+ message: `Inline script has invalid syntax: ${syntaxError}`,
102190
+ fixHint: "Fix the inline script syntax before render verification.",
102191
+ snippet: truncateSnippet(script.content)
102247
102192
  });
102248
102193
  }
102249
- if (!localTimelineCompId || localTimelineCompId === rootCompositionId) {
102250
- continue;
102194
+ return findings;
102195
+ },
102196
+ // host_missing_composition_id
102197
+ ({ tags }) => {
102198
+ const findings = [];
102199
+ for (const tag of tags) {
102200
+ const src = readAttr(tag.raw, "data-composition-src");
102201
+ if (!src) continue;
102202
+ if (readAttr(tag.raw, "data-composition-id")) continue;
102203
+ findings.push({
102204
+ code: "host_missing_composition_id",
102205
+ severity: "error",
102206
+ message: `Composition host for "${src}" is missing \`data-composition-id\`.`,
102207
+ elementId: readAttr(tag.raw, "id") || void 0,
102208
+ fixHint: "Set `data-composition-id` on every `data-composition-src` host element.",
102209
+ snippet: truncateSnippet(tag.raw)
102210
+ });
102251
102211
  }
102252
- for (const win of gsapWindows) {
102253
- if (!isSuspiciousGlobalSelector(win.targetSelector)) {
102254
- continue;
102255
- }
102256
- const className = getSingleClassSelector(win.targetSelector);
102257
- if (className && (classUsage.get(className) || 0) < 2) {
102258
- continue;
102212
+ return findings;
102213
+ },
102214
+ // scoped_css_missing_wrapper
102215
+ ({ styles, compositionIds }) => {
102216
+ const findings = [];
102217
+ const scopedCssCompositionIds = /* @__PURE__ */ new Set();
102218
+ for (const style of styles) {
102219
+ for (const compId of extractCompositionIdsFromCss(style.content)) {
102220
+ scopedCssCompositionIds.add(compId);
102259
102221
  }
102260
- pushFinding({
102261
- code: "unscoped_gsap_selector",
102222
+ }
102223
+ for (const compId of scopedCssCompositionIds) {
102224
+ if (compositionIds.has(compId)) continue;
102225
+ findings.push({
102226
+ code: "scoped_css_missing_wrapper",
102262
102227
  severity: "warning",
102263
- message: `Timeline "${localTimelineCompId}" uses unscoped selector "${win.targetSelector}" that will target elements in ALL compositions when bundled, causing data loss (opacity, transforms, etc.).`,
102264
- selector: win.targetSelector,
102265
- fixHint: `Scope the selector: \`[data-composition-id="${localTimelineCompId}"] ${win.targetSelector}\` or use a unique id.`,
102266
- snippet: truncateSnippet(win.raw)
102228
+ message: `Scoped CSS targets composition "${compId}" but no matching wrapper exists in this HTML.`,
102229
+ selector: `[data-composition-id="${compId}"]`,
102230
+ fixHint: "Preserve the matching composition wrapper or align the CSS scope to an existing wrapper."
102267
102231
  });
102268
102232
  }
102233
+ return findings;
102269
102234
  }
102270
- for (const tag of tags) {
102271
- if (tag.name !== "video") continue;
102272
- const hasMuted = /\bmuted\b/i.test(tag.raw);
102273
- if (!hasMuted && readAttr(tag.raw, "data-start")) {
102274
- const elementId = readAttr(tag.raw, "id") || void 0;
102275
- pushFinding({
102276
- code: "video_missing_muted",
102235
+ ];
102236
+
102237
+ // ../core/src/lint/rules/media.ts
102238
+ var mediaRules = [
102239
+ // duplicate_media_id + duplicate_media_discovery_risk
102240
+ ({ tags }) => {
102241
+ const findings = [];
102242
+ const mediaById = /* @__PURE__ */ new Map();
102243
+ const mediaFingerprintCounts = /* @__PURE__ */ new Map();
102244
+ for (const tag of tags) {
102245
+ if (!isMediaTag(tag.name)) continue;
102246
+ const elementId = readAttr(tag.raw, "id");
102247
+ if (elementId) {
102248
+ const existing = mediaById.get(elementId) || [];
102249
+ existing.push(tag);
102250
+ mediaById.set(elementId, existing);
102251
+ }
102252
+ const fingerprint = [
102253
+ tag.name,
102254
+ readAttr(tag.raw, "src") || "",
102255
+ readAttr(tag.raw, "data-start") || "",
102256
+ readAttr(tag.raw, "data-duration") || ""
102257
+ ].join("|");
102258
+ mediaFingerprintCounts.set(fingerprint, (mediaFingerprintCounts.get(fingerprint) || 0) + 1);
102259
+ }
102260
+ for (const [elementId, mediaTags] of mediaById) {
102261
+ if (mediaTags.length < 2) continue;
102262
+ findings.push({
102263
+ code: "duplicate_media_id",
102277
102264
  severity: "error",
102278
- message: `<video${elementId ? ` id="${elementId}"` : ""}> has data-start but is not muted. The framework expects video to be muted with a separate <audio> element for sound.`,
102265
+ message: `Media id "${elementId}" is defined multiple times.`,
102279
102266
  elementId,
102280
- fixHint: "Add the `muted` attribute to the <video> tag and use a separate <audio> element with the same src for audio playback.",
102281
- snippet: truncateSnippet(tag.raw)
102267
+ fixHint: "Give each media element a unique id so preview and producer discover the same media graph.",
102268
+ snippet: truncateSnippet(mediaTags[0]?.raw || "")
102282
102269
  });
102283
102270
  }
102284
- }
102285
- const timedTagPositions = [];
102286
- for (const tag of tags) {
102287
- if (tag.name === "video" || tag.name === "audio") continue;
102288
- if (readAttr(tag.raw, "data-start")) {
102289
- timedTagPositions.push({
102290
- name: tag.name,
102291
- start: tag.index,
102292
- id: readAttr(tag.raw, "id") || void 0
102271
+ for (const [fingerprint, count] of mediaFingerprintCounts) {
102272
+ if (count < 2) continue;
102273
+ const [tagName19, src, dataStart, dataDuration] = fingerprint.split("|");
102274
+ findings.push({
102275
+ code: "duplicate_media_discovery_risk",
102276
+ severity: "warning",
102277
+ message: `Detected ${count} matching ${tagName19} entries with the same source/start/duration.`,
102278
+ fixHint: "Avoid duplicated media nodes that can be discovered twice during compilation.",
102279
+ snippet: truncateSnippet(
102280
+ `${tagName19} src=${src} data-start=${dataStart} data-duration=${dataDuration}`
102281
+ )
102293
102282
  });
102294
102283
  }
102295
- }
102296
- for (const tag of tags) {
102297
- if (tag.name !== "video") continue;
102298
- if (!readAttr(tag.raw, "data-start")) continue;
102299
- for (const parent of timedTagPositions) {
102300
- if (parent.start < tag.index) {
102301
- const parentClosePattern = new RegExp(`</${parent.name}>`, "gi");
102302
- const between = source2.substring(parent.start, tag.index);
102303
- if (!parentClosePattern.test(between)) {
102304
- pushFinding({
102305
- code: "video_nested_in_timed_element",
102306
- severity: "error",
102307
- message: `<video> with data-start is nested inside <${parent.name}${parent.id ? ` id="${parent.id}"` : ""}> which also has data-start. The framework cannot manage playback of nested media \u2014 video will be FROZEN in renders.`,
102308
- elementId: readAttr(tag.raw, "id") || void 0,
102309
- fixHint: "Move the <video> to be a direct child of the stage, or remove data-start from the wrapper div (use it as a non-timed visual container).",
102310
- snippet: truncateSnippet(tag.raw)
102311
- });
102312
- break;
102284
+ return findings;
102285
+ },
102286
+ // video_missing_muted
102287
+ ({ tags }) => {
102288
+ const findings = [];
102289
+ for (const tag of tags) {
102290
+ if (tag.name !== "video") continue;
102291
+ const hasMuted = /\bmuted\b/i.test(tag.raw);
102292
+ if (!hasMuted && readAttr(tag.raw, "data-start")) {
102293
+ const elementId = readAttr(tag.raw, "id") || void 0;
102294
+ findings.push({
102295
+ code: "video_missing_muted",
102296
+ severity: "error",
102297
+ message: `<video${elementId ? ` id="${elementId}"` : ""}> has data-start but is not muted. The framework expects video to be muted with a separate <audio> element for sound.`,
102298
+ elementId,
102299
+ fixHint: "Add the `muted` attribute to the <video> tag and use a separate <audio> element with the same src for audio playback.",
102300
+ snippet: truncateSnippet(tag.raw)
102301
+ });
102302
+ }
102303
+ }
102304
+ return findings;
102305
+ },
102306
+ // video_nested_in_timed_element
102307
+ ({ source: source2, tags }) => {
102308
+ const findings = [];
102309
+ const timedTagPositions = [];
102310
+ for (const tag of tags) {
102311
+ if (tag.name === "video" || tag.name === "audio") continue;
102312
+ if (readAttr(tag.raw, "data-start")) {
102313
+ timedTagPositions.push({
102314
+ name: tag.name,
102315
+ start: tag.index,
102316
+ id: readAttr(tag.raw, "id") || void 0
102317
+ });
102318
+ }
102319
+ }
102320
+ for (const tag of tags) {
102321
+ if (tag.name !== "video") continue;
102322
+ if (!readAttr(tag.raw, "data-start")) continue;
102323
+ for (const parent of timedTagPositions) {
102324
+ if (parent.start < tag.index) {
102325
+ const parentClosePattern = new RegExp(`</${parent.name}>`, "gi");
102326
+ const between = source2.substring(parent.start, tag.index);
102327
+ if (!parentClosePattern.test(between)) {
102328
+ findings.push({
102329
+ code: "video_nested_in_timed_element",
102330
+ severity: "error",
102331
+ message: `<video> with data-start is nested inside <${parent.name}${parent.id ? ` id="${parent.id}"` : ""}> which also has data-start. The framework cannot manage playback of nested media \u2014 video will be FROZEN in renders.`,
102332
+ elementId: readAttr(tag.raw, "id") || void 0,
102333
+ fixHint: "Move the <video> to be a direct child of the stage, or remove data-start from the wrapper div (use it as a non-timed visual container).",
102334
+ snippet: truncateSnippet(tag.raw)
102335
+ });
102336
+ break;
102337
+ }
102313
102338
  }
102314
102339
  }
102315
102340
  }
102316
- }
102317
- {
102341
+ return findings;
102342
+ },
102343
+ // self_closing_media_tag
102344
+ ({ source: source2 }) => {
102345
+ const findings = [];
102318
102346
  const selfClosingMediaRe = /<(audio|video)\b[^>]*\/>/gi;
102319
102347
  let scMatch;
102320
102348
  while ((scMatch = selfClosingMediaRe.exec(source2)) !== null) {
102321
102349
  const tagName19 = scMatch[1] || "audio";
102322
102350
  const elementId = readAttr(scMatch[0], "id") || void 0;
102323
- pushFinding({
102351
+ findings.push({
102324
102352
  code: "self_closing_media_tag",
102325
102353
  severity: "error",
102326
102354
  message: `Self-closing <${tagName19}/> is invalid HTML. The browser will leave the tag open, swallowing all subsequent elements as invisible fallback content. This makes compositions INVISIBLE.`,
@@ -102329,8 +102357,11 @@ ${right2.raw}`)
102329
102357
  snippet: truncateSnippet(scMatch[0])
102330
102358
  });
102331
102359
  }
102332
- }
102333
- {
102360
+ return findings;
102361
+ },
102362
+ // placeholder_media_url
102363
+ ({ tags }) => {
102364
+ const findings = [];
102334
102365
  const PLACEHOLDER_DOMAINS = /\b(placehold\.co|placeholder\.com|placekitten\.com|picsum\.photos|example\.com|via\.placeholder\.com|dummyimage\.com)\b/i;
102335
102366
  for (const tag of tags) {
102336
102367
  if (!isMediaTag(tag.name)) continue;
@@ -102338,7 +102369,7 @@ ${right2.raw}`)
102338
102369
  if (!src) continue;
102339
102370
  if (PLACEHOLDER_DOMAINS.test(src)) {
102340
102371
  const elementId = readAttr(tag.raw, "id") || void 0;
102341
- pushFinding({
102372
+ findings.push({
102342
102373
  code: "placeholder_media_url",
102343
102374
  severity: "error",
102344
102375
  message: `<${tag.name}${elementId ? ` id="${elementId}"` : ""}> uses a placeholder URL that will 404 at render time: ${src.slice(0, 80)}`,
@@ -102348,8 +102379,11 @@ ${right2.raw}`)
102348
102379
  });
102349
102380
  }
102350
102381
  }
102351
- }
102352
- {
102382
+ return findings;
102383
+ },
102384
+ // base64_media_prohibited
102385
+ ({ source: source2 }) => {
102386
+ const findings = [];
102353
102387
  const base64MediaRe = /src\s*=\s*["'](data:(?:audio|video)\/[^;]+;base64,([A-Za-z0-9+/=]{20,}))["']/gi;
102354
102388
  let b64Match;
102355
102389
  while ((b64Match = base64MediaRe.exec(source2)) !== null) {
@@ -102357,7 +102391,7 @@ ${right2.raw}`)
102357
102391
  const uniqueChars = new Set(sample.replace(/[A-Za-z0-9+/=]/g, (c) => c)).size;
102358
102392
  const dataSize = Math.round((b64Match[2] || "").length * 3 / 4);
102359
102393
  const isSuspicious = uniqueChars < 15 || dataSize > 1e3 && dataSize < 5e4;
102360
- pushFinding({
102394
+ findings.push({
102361
102395
  code: "base64_media_prohibited",
102362
102396
  severity: "error",
102363
102397
  message: `Inline base64 audio/video detected (${(dataSize / 1024).toFixed(0)} KB)${isSuspicious ? " \u2014 likely fabricated data" : ""}. Base64 media is prohibited \u2014 it bloats file size and breaks rendering.`,
@@ -102365,331 +102399,57 @@ ${right2.raw}`)
102365
102399
  snippet: truncateSnippet((b64Match[1] ?? "").slice(0, 80) + "...")
102366
102400
  });
102367
102401
  }
102368
- }
102369
- for (const tag of tags) {
102370
- if (tag.name !== "video" && tag.name !== "audio") continue;
102371
- const hasDataStart = readAttr(tag.raw, "data-start");
102372
- const hasId = readAttr(tag.raw, "id");
102373
- const hasSrc = readAttr(tag.raw, "src");
102374
- if (hasDataStart && !hasId) {
102375
- pushFinding({
102376
- code: "media_missing_id",
102377
- severity: "error",
102378
- message: `<${tag.name}> has data-start but no id attribute. The renderer requires id to discover media elements \u2014 this ${tag.name === "audio" ? "audio will be SILENT" : "video will be FROZEN"} in renders.`,
102379
- fixHint: `Add a unique id attribute: <${tag.name} id="my-${tag.name}" ...>`,
102380
- snippet: truncateSnippet(tag.raw)
102381
- });
102382
- }
102383
- if (hasDataStart && hasId && !hasSrc) {
102384
- pushFinding({
102385
- code: "media_missing_src",
102386
- severity: "error",
102387
- message: `<${tag.name} id="${hasId}"> has data-start but no src attribute. The renderer cannot load this media.`,
102388
- elementId: hasId,
102389
- fixHint: `Add a src attribute to the <${tag.name}> element directly. If using <source> children, the renderer still requires src on the parent element.`,
102390
- snippet: truncateSnippet(tag.raw)
102391
- });
102392
- }
102393
- if (readAttr(tag.raw, "preload") === "none") {
102394
- pushFinding({
102395
- code: "media_preload_none",
102396
- severity: "warning",
102397
- message: `<${tag.name}${hasId ? ` id="${hasId}"` : ""}> has preload="none" which prevents the renderer from loading this media. The compiler strips it for renders, but preview may also have issues.`,
102398
- elementId: hasId || void 0,
102399
- fixHint: `Remove preload="none" or change to preload="auto". The framework manages media loading.`,
102400
- snippet: truncateSnippet(tag.raw)
102401
- });
102402
- }
102403
- }
102404
- for (const tag of tags) {
102405
- if (tag.name === "audio" || tag.name === "script" || tag.name === "style") continue;
102406
- if (!readAttr(tag.raw, "data-start")) continue;
102407
- if (readAttr(tag.raw, "data-composition-id")) continue;
102408
- if (readAttr(tag.raw, "data-composition-src")) continue;
102409
- const classAttr = readAttr(tag.raw, "class") || "";
102410
- const styleAttr = readAttr(tag.raw, "style") || "";
102411
- const hasClip = classAttr.split(/\s+/).includes("clip");
102412
- const hasHiddenStyle = /visibility\s*:\s*hidden/i.test(styleAttr) || /opacity\s*:\s*0/i.test(styleAttr);
102413
- if (!hasClip && !hasHiddenStyle) {
102414
- const elementId = readAttr(tag.raw, "id") || void 0;
102415
- pushFinding({
102416
- code: "timed_element_missing_visibility_hidden",
102417
- severity: "info",
102418
- message: `<${tag.name}${elementId ? ` id="${elementId}"` : ""}> has data-start but no class="clip", visibility:hidden, or opacity:0. Consider adding initial hidden state if the element should not be visible before its start time.`,
102419
- elementId,
102420
- fixHint: 'Add class="clip" (with CSS: .clip { visibility: hidden; }) or style="opacity:0" if the element should start hidden.',
102421
- snippet: truncateSnippet(tag.raw)
102422
- });
102423
- }
102424
- }
102425
- for (const tag of tags) {
102426
- if (readAttr(tag.raw, "data-layer") && !readAttr(tag.raw, "data-track-index")) {
102427
- const elementId = readAttr(tag.raw, "id") || void 0;
102428
- pushFinding({
102429
- code: "deprecated_data_layer",
102430
- severity: "warning",
102431
- message: `<${tag.name}${elementId ? ` id="${elementId}"` : ""}> uses data-layer instead of data-track-index.`,
102432
- elementId,
102433
- fixHint: "Replace data-layer with data-track-index. The runtime reads data-track-index.",
102434
- snippet: truncateSnippet(tag.raw)
102435
- });
102436
- }
102437
- if (readAttr(tag.raw, "data-end") && !readAttr(tag.raw, "data-duration")) {
102438
- const elementId = readAttr(tag.raw, "id") || void 0;
102439
- pushFinding({
102440
- code: "deprecated_data_end",
102441
- severity: "warning",
102442
- message: `<${tag.name}${elementId ? ` id="${elementId}"` : ""}> uses data-end without data-duration. Use data-duration in source HTML.`,
102443
- elementId,
102444
- fixHint: "Replace data-end with data-duration. The compiler generates data-end from data-duration automatically.",
102445
- snippet: truncateSnippet(tag.raw)
102446
- });
102447
- }
102448
- }
102449
- for (const script of scripts) {
102450
- const templateLiteralSelectorPattern = /(?:querySelector|querySelectorAll)\s*\(\s*`[^`]*\$\{[^}]+\}[^`]*`\s*\)/g;
102451
- let tlMatch;
102452
- while ((tlMatch = templateLiteralSelectorPattern.exec(script.content)) !== null) {
102453
- pushFinding({
102454
- code: "template_literal_selector",
102455
- severity: "error",
102456
- message: "querySelector uses a template literal variable (e.g. `${compId}`). The HTML bundler's CSS parser crashes on these. Use a hardcoded string instead.",
102457
- file: filePath,
102458
- fixHint: "Replace the template literal variable with a hardcoded string. The bundler's CSS parser cannot handle interpolated variables in script content.",
102459
- snippet: truncateSnippet(tlMatch[0])
102460
- });
102461
- }
102462
- }
102463
- {
102464
- const cssTranslateSelectors = /* @__PURE__ */ new Map();
102465
- const cssScaleSelectors = /* @__PURE__ */ new Map();
102466
- for (const style of styles) {
102467
- for (const [, selector, body] of style.content.matchAll(
102468
- /([#.][a-zA-Z0-9_-]+)\s*\{([^}]+)\}/g
102469
- )) {
102470
- const tMatch = body?.match(/transform\s*:\s*([^;]+)/);
102471
- if (!tMatch || !tMatch[1]) continue;
102472
- const transformVal = tMatch[1].trim();
102473
- if (/translate/i.test(transformVal)) {
102474
- cssTranslateSelectors.set((selector ?? "").trim(), transformVal);
102475
- }
102476
- if (/scale/i.test(transformVal)) {
102477
- cssScaleSelectors.set((selector ?? "").trim(), transformVal);
102478
- }
102479
- }
102480
- }
102481
- if (cssTranslateSelectors.size > 0 || cssScaleSelectors.size > 0) {
102482
- for (const script of scripts) {
102483
- if (!/gsap\.timeline/.test(script.content)) continue;
102484
- const windows = extractGsapWindows(script.content);
102485
- const conflicts = /* @__PURE__ */ new Map();
102486
- for (const win of windows) {
102487
- if (win.method === "fromTo") continue;
102488
- const sel = win.targetSelector;
102489
- const cssKey = sel.startsWith("#") || sel.startsWith(".") ? sel : `#${sel}`;
102490
- const translateProps = win.properties.filter(
102491
- (p) => ["x", "y", "xPercent", "yPercent"].includes(p)
102492
- );
102493
- const scaleProps = win.properties.filter((p) => p === "scale");
102494
- const cssFromTranslate = translateProps.length > 0 ? cssTranslateSelectors.get(cssKey) : void 0;
102495
- const cssFromScale = scaleProps.length > 0 ? cssScaleSelectors.get(cssKey) : void 0;
102496
- if (!cssFromTranslate && !cssFromScale) continue;
102497
- const existing = conflicts.get(sel) ?? {
102498
- cssTransform: [cssFromTranslate, cssFromScale].filter(Boolean).join(" "),
102499
- props: /* @__PURE__ */ new Set(),
102500
- raw: win.raw
102501
- };
102502
- for (const p of [...translateProps, ...scaleProps]) existing.props.add(p);
102503
- conflicts.set(sel, existing);
102504
- }
102505
- for (const [sel, { cssTransform, props, raw: raw2 }] of conflicts) {
102506
- const propList = [...props].join("/");
102507
- pushFinding({
102508
- code: "gsap_css_transform_conflict",
102509
- severity: "warning",
102510
- message: `"${sel}" has CSS \`transform: ${cssTransform}\` and a GSAP tween animates ${propList}. GSAP will overwrite the full CSS transform, discarding any translateX(-50%) centering or CSS scale value.`,
102511
- selector: sel,
102512
- fixHint: `Remove the transform from CSS and use tl.fromTo('${sel}', { xPercent: -50, x: -1000 }, { xPercent: -50, x: 0 }) so GSAP owns the full transform state. tl.fromTo is exempt from this rule.`,
102513
- snippet: truncateSnippet(raw2)
102514
- });
102515
- }
102402
+ return findings;
102403
+ },
102404
+ // media_missing_id + media_missing_src + media_preload_none
102405
+ ({ tags }) => {
102406
+ const findings = [];
102407
+ for (const tag of tags) {
102408
+ if (tag.name !== "video" && tag.name !== "audio") continue;
102409
+ const hasDataStart = readAttr(tag.raw, "data-start");
102410
+ const hasId = readAttr(tag.raw, "id");
102411
+ const hasSrc = readAttr(tag.raw, "src");
102412
+ if (hasDataStart && !hasId) {
102413
+ findings.push({
102414
+ code: "media_missing_id",
102415
+ severity: "error",
102416
+ message: `<${tag.name}> has data-start but no id attribute. The renderer requires id to discover media elements \u2014 this ${tag.name === "audio" ? "audio will be SILENT" : "video will be FROZEN"} in renders.`,
102417
+ fixHint: `Add a unique id attribute: <${tag.name} id="my-${tag.name}" ...>`,
102418
+ snippet: truncateSnippet(tag.raw)
102419
+ });
102516
102420
  }
102517
- }
102518
- }
102519
- for (const script of scripts) {
102520
- const content = script.content;
102521
- const hasExitTween = /\.to\s*\([^,]+,\s*\{[^}]*opacity\s*:\s*0/.test(content);
102522
- const hasHardKill = /\.set\s*\([^,]+,\s*\{[^}]*(?:visibility\s*:\s*["']hidden["']|opacity\s*:\s*0)/.test(content);
102523
- const hasCaptionLoop = /forEach|\.forEach\s*\(/.test(content) && /createElement|caption|group|cg-/.test(content);
102524
- if (hasCaptionLoop && hasExitTween && !hasHardKill) {
102525
- pushFinding({
102526
- code: "caption_exit_missing_hard_kill",
102527
- severity: "warning",
102528
- message: "Caption exit animations (tl.to with opacity: 0) detected without a hard tl.set kill. Exit tweens can fail when karaoke word-level tweens conflict, leaving captions stuck on screen.",
102529
- fixHint: 'Add `tl.set(groupEl, { opacity: 0, visibility: "hidden" }, group.end)` after every exit tl.to animation as a deterministic kill.'
102530
- });
102531
- }
102532
- }
102533
- for (const style of styles) {
102534
- const content = style.content;
102535
- const captionBlocks = content.matchAll(
102536
- /(\.caption[-_]?(?:group|container|text|line|word)|#caption[-_]?container)\s*\{([^}]+)\}/gi
102537
- );
102538
- for (const [, selector, body] of captionBlocks) {
102539
- if (!body) continue;
102540
- const hasNowrap = /white-space\s*:\s*nowrap/i.test(body);
102541
- const hasMaxWidth = /max-width/i.test(body);
102542
- if (hasNowrap && !hasMaxWidth) {
102543
- pushFinding({
102544
- code: "caption_text_overflow_risk",
102545
- severity: "warning",
102546
- selector: (selector ?? "").trim(),
102547
- message: `Caption selector "${(selector ?? "").trim()}" has white-space: nowrap but no max-width. Long phrases will clip off-screen.`,
102548
- fixHint: "Add max-width: 1600px (landscape) or max-width: 900px (portrait) and overflow: hidden."
102421
+ if (hasDataStart && hasId && !hasSrc) {
102422
+ findings.push({
102423
+ code: "media_missing_src",
102424
+ severity: "error",
102425
+ message: `<${tag.name} id="${hasId}"> has data-start but no src attribute. The renderer cannot load this media.`,
102426
+ elementId: hasId,
102427
+ fixHint: `Add a src attribute to the <${tag.name}> element directly. If using <source> children, the renderer still requires src on the parent element.`,
102428
+ snippet: truncateSnippet(tag.raw)
102549
102429
  });
102550
102430
  }
102551
- }
102552
- }
102553
- for (const style of styles) {
102554
- const content = style.content;
102555
- const captionBlocks = content.matchAll(
102556
- /(\.caption[-_]?(?:group|container|text|line)|#caption[-_]?container)\s*\{([^}]+)\}/gi
102557
- );
102558
- for (const [, selector, body] of captionBlocks) {
102559
- if (!body) continue;
102560
- if (/position\s*:\s*relative/i.test(body)) {
102561
- pushFinding({
102562
- code: "caption_container_relative_position",
102431
+ if (readAttr(tag.raw, "preload") === "none") {
102432
+ findings.push({
102433
+ code: "media_preload_none",
102563
102434
  severity: "warning",
102564
- selector: (selector ?? "").trim(),
102565
- message: `Caption selector "${(selector ?? "").trim()}" uses position: relative which causes overflow and breaks caption stacking.`,
102566
- fixHint: "Use position: absolute for all caption elements."
102435
+ message: `<${tag.name}${hasId ? ` id="${hasId}"` : ""}> has preload="none" which prevents the renderer from loading this media. The compiler strips it for renders, but preview may also have issues.`,
102436
+ elementId: hasId || void 0,
102437
+ fixHint: `Remove preload="none" or change to preload="auto". The framework manages media loading.`,
102438
+ snippet: truncateSnippet(tag.raw)
102567
102439
  });
102568
102440
  }
102569
102441
  }
102442
+ return findings;
102570
102443
  }
102571
- {
102572
- const externalScriptRe = /<script\b[^>]*\bsrc=["'](https?:\/\/[^"']+)["'][^>]*>/gi;
102573
- let match2;
102574
- const seen2 = /* @__PURE__ */ new Set();
102575
- while ((match2 = externalScriptRe.exec(source2)) !== null) {
102576
- const src = match2[1] ?? "";
102577
- if (seen2.has(src)) continue;
102578
- seen2.add(src);
102579
- pushFinding({
102580
- code: "external_script_dependency",
102581
- severity: "info",
102582
- message: `This composition loads an external script from \`${src}\`. The HyperFrames bundler automatically hoists CDN scripts from sub-compositions into the parent document. In unbundled runtime mode, \`loadExternalCompositions\` re-injects them. If you're using a custom pipeline that bypasses both, you'll need to include this script manually.`,
102583
- fixHint: "No action needed when using `hyperframes dev` or `hyperframes render`. If using a custom pipeline, add this script tag to your root composition or HTML page.",
102584
- snippet: truncateSnippet(match2[0] ?? "")
102585
- });
102586
- }
102587
- }
102588
- const errorCount = findings.filter((finding) => finding.severity === "error").length;
102589
- const warningCount = findings.filter((finding) => finding.severity === "warning").length;
102590
- const infoCount = findings.filter((finding) => finding.severity === "info").length;
102591
- return {
102592
- ok: errorCount === 0,
102593
- errorCount,
102594
- warningCount,
102595
- infoCount,
102596
- findings
102597
- };
102598
- }
102599
- function extractOpenTags(source2) {
102600
- const tags = [];
102601
- let match2;
102602
- while ((match2 = TAG_PATTERN.exec(source2)) !== null) {
102603
- const raw2 = match2[0];
102604
- if (raw2.startsWith("</") || raw2.startsWith("<!")) {
102605
- continue;
102606
- }
102607
- tags.push({
102608
- raw: raw2,
102609
- name: (match2[1] || "").toLowerCase(),
102610
- attrs: match2[2] || "",
102611
- index: match2.index
102612
- });
102613
- }
102614
- return tags;
102615
- }
102616
- function extractBlocks(source2, pattern) {
102617
- const blocks = [];
102618
- let match2;
102619
- while ((match2 = pattern.exec(source2)) !== null) {
102620
- blocks.push({
102621
- attrs: match2[1] || "",
102622
- content: match2[2] || "",
102623
- raw: match2[0],
102624
- index: match2.index
102625
- });
102626
- }
102627
- return blocks;
102628
- }
102629
- function findRootTag(source2) {
102630
- const bodyMatch = source2.match(/<body\b[^>]*>([\s\S]*?)<\/body>/i);
102631
- const bodyContent = bodyMatch ? bodyMatch[1] ?? source2 : source2;
102632
- const bodyTags = extractOpenTags(bodyContent);
102633
- for (const tag of bodyTags) {
102634
- if (["script", "style", "meta", "link", "title"].includes(tag.name)) {
102635
- continue;
102636
- }
102637
- return tag;
102638
- }
102639
- return null;
102640
- }
102641
- function readAttr(tagSource, attr) {
102642
- if (!tagSource) {
102643
- return null;
102644
- }
102645
- const escaped = attr.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
102646
- const match2 = tagSource.match(new RegExp(`\\b${escaped}\\s*=\\s*["']([^"']+)["']`, "i"));
102647
- return match2?.[1] || null;
102648
- }
102649
- function collectCompositionIds(tags) {
102650
- const ids = /* @__PURE__ */ new Set();
102651
- for (const tag of tags) {
102652
- const compId = readAttr(tag.raw, "data-composition-id");
102653
- if (compId) {
102654
- ids.add(compId);
102655
- }
102656
- }
102657
- return ids;
102658
- }
102659
- function extractCompositionIdsFromCss(css) {
102660
- const ids = /* @__PURE__ */ new Set();
102661
- let match2;
102662
- while ((match2 = COMPOSITION_ID_IN_CSS_PATTERN.exec(css)) !== null) {
102663
- if (match2[1]) {
102664
- ids.add(match2[1]);
102665
- }
102666
- }
102667
- return [...ids];
102668
- }
102669
- function getInlineScriptSyntaxError(source2) {
102670
- if (!source2.trim()) {
102671
- return null;
102672
- }
102673
- try {
102674
- new Function(source2);
102675
- return null;
102676
- } catch (error) {
102677
- if (error instanceof Error) {
102678
- return error.message;
102679
- }
102680
- return String(error);
102681
- }
102682
- }
102683
- function isMediaTag(tagName19) {
102684
- return tagName19 === "video" || tagName19 === "audio" || tagName19 === "img";
102685
- }
102444
+ ];
102445
+
102446
+ // ../core/src/lint/rules/gsap.ts
102447
+ var META_GSAP_KEYS = /* @__PURE__ */ new Set(["duration", "ease", "repeat", "yoyo", "overwrite", "delay"]);
102686
102448
  function countClassUsage(tags) {
102687
102449
  const counts = /* @__PURE__ */ new Map();
102688
102450
  for (const tag of tags) {
102689
102451
  const classAttr = readAttr(tag.raw, "class");
102690
- if (!classAttr) {
102691
- continue;
102692
- }
102452
+ if (!classAttr) continue;
102693
102453
  for (const className of classAttr.split(/\s+/).filter(Boolean)) {
102694
102454
  counts.set(className, (counts.get(className) || 0) + 1);
102695
102455
  }
@@ -102701,13 +102461,9 @@ function readRegisteredTimelineCompositionId(script) {
102701
102461
  return match2?.[1] || null;
102702
102462
  }
102703
102463
  function extractGsapWindows(script) {
102704
- if (!/gsap\.timeline/.test(script)) {
102705
- return [];
102706
- }
102464
+ if (!/gsap\.timeline/.test(script)) return [];
102707
102465
  const parsed = parseGsapScript(script);
102708
- if (parsed.animations.length === 0) {
102709
- return [];
102710
- }
102466
+ if (parsed.animations.length === 0) return [];
102711
102467
  const windows = [];
102712
102468
  const timelineVar = parsed.timelineVar;
102713
102469
  const methodPattern = new RegExp(
@@ -102721,9 +102477,7 @@ function extractGsapWindows(script) {
102721
102477
  const meta = parseGsapWindowMeta(match2[1] ?? "", match2[2] ?? "");
102722
102478
  const animation = parsed.animations[index];
102723
102479
  index += 1;
102724
- if (!animation) {
102725
- continue;
102726
- }
102480
+ if (!animation) continue;
102727
102481
  windows.push({
102728
102482
  targetSelector: animation.targetSelector,
102729
102483
  position: animation.position,
@@ -102738,9 +102492,7 @@ function extractGsapWindows(script) {
102738
102492
  }
102739
102493
  function parseGsapWindowMeta(method, argsStr) {
102740
102494
  const selectorMatch = argsStr.match(/^\s*["']([^"']+)["']\s*,/);
102741
- if (!selectorMatch) {
102742
- return { effectiveDuration: 0, properties: [], overwriteAuto: false };
102743
- }
102495
+ if (!selectorMatch) return { effectiveDuration: 0, properties: [], overwriteAuto: false };
102744
102496
  const afterSelector = argsStr.slice(selectorMatch[0].length);
102745
102497
  let properties = {};
102746
102498
  let fromProperties = {};
@@ -102765,20 +102517,15 @@ function parseGsapWindowMeta(method, argsStr) {
102765
102517
  }
102766
102518
  const duration = numberValue(properties.duration) || 0;
102767
102519
  const repeat = numberValue(properties.repeat) || 0;
102768
- const yoyo = stringValue(properties.yoyo) === "true";
102769
102520
  const cycleCount = repeat > 0 ? repeat + 1 : 1;
102770
- const effectiveDuration = duration * cycleCount * (yoyo ? 1 : 1);
102521
+ const effectiveDuration = duration * cycleCount;
102771
102522
  const overwriteAuto = stringValue(properties.overwrite) === "auto";
102772
102523
  const propertyNames = /* @__PURE__ */ new Set();
102773
102524
  for (const key2 of Object.keys(fromProperties)) {
102774
- if (!META_GSAP_KEYS.has(key2)) {
102775
- propertyNames.add(key2);
102776
- }
102525
+ if (!META_GSAP_KEYS.has(key2)) propertyNames.add(key2);
102777
102526
  }
102778
102527
  for (const key2 of Object.keys(properties)) {
102779
- if (!META_GSAP_KEYS.has(key2)) {
102780
- propertyNames.add(key2);
102781
- }
102528
+ if (!META_GSAP_KEYS.has(key2)) propertyNames.add(key2);
102782
102529
  }
102783
102530
  return {
102784
102531
  effectiveDuration: method === "set" ? 0 : effectiveDuration,
@@ -102789,17 +102536,13 @@ function parseGsapWindowMeta(method, argsStr) {
102789
102536
  function parseLooseObjectLiteral(source2) {
102790
102537
  const result = {};
102791
102538
  const cleaned = source2.replace(/^\{|\}$/g, "").trim();
102792
- if (!cleaned) {
102793
- return result;
102794
- }
102539
+ if (!cleaned) return result;
102795
102540
  const propertyPattern = /(\w+)\s*:\s*("[^"]*"|'[^']*'|true|false|-?[\d.]+|[a-zA-Z_][\w.]*)/g;
102796
102541
  let match2;
102797
102542
  while ((match2 = propertyPattern.exec(cleaned)) !== null) {
102798
102543
  const key2 = match2[1];
102799
102544
  const rawValue = match2[2];
102800
- if (!key2 || rawValue == null) {
102801
- continue;
102802
- }
102545
+ if (!key2 || rawValue == null) continue;
102803
102546
  if (rawValue.startsWith('"') && rawValue.endsWith('"') || rawValue.startsWith("'") && rawValue.endsWith("'")) {
102804
102547
  result[key2] = rawValue.slice(1, -1);
102805
102548
  continue;
@@ -102810,26 +102553,19 @@ function parseLooseObjectLiteral(source2) {
102810
102553
  return result;
102811
102554
  }
102812
102555
  function findMatchingBrace2(source2, startIndex) {
102813
- if (startIndex < 0) {
102814
- return -1;
102815
- }
102556
+ if (startIndex < 0) return -1;
102816
102557
  let depth = 0;
102817
102558
  for (let i = startIndex; i < source2.length; i++) {
102818
- if (source2[i] === "{") {
102819
- depth += 1;
102820
- } else if (source2[i] === "}") {
102559
+ if (source2[i] === "{") depth += 1;
102560
+ else if (source2[i] === "}") {
102821
102561
  depth -= 1;
102822
- if (depth === 0) {
102823
- return i;
102824
- }
102562
+ if (depth === 0) return i;
102825
102563
  }
102826
102564
  }
102827
102565
  return -1;
102828
102566
  }
102829
102567
  function numberValue(value) {
102830
- if (typeof value === "number") {
102831
- return value;
102832
- }
102568
+ if (typeof value === "number") return value;
102833
102569
  if (typeof value === "string" && value.trim()) {
102834
102570
  const numeric = Number(value);
102835
102571
  return Number.isFinite(numeric) ? numeric : null;
@@ -102837,39 +102573,451 @@ function numberValue(value) {
102837
102573
  return null;
102838
102574
  }
102839
102575
  function stringValue(value) {
102840
- if (typeof value === "string") {
102841
- return value;
102842
- }
102843
- if (typeof value === "number") {
102844
- return String(value);
102845
- }
102576
+ if (typeof value === "string") return value;
102577
+ if (typeof value === "number") return String(value);
102846
102578
  return null;
102847
102579
  }
102848
102580
  function isSuspiciousGlobalSelector(selector) {
102849
- if (!selector) {
102850
- return false;
102851
- }
102852
- if (selector.includes("[data-composition-id=")) {
102853
- return false;
102854
- }
102855
- if (selector.startsWith("#")) {
102856
- return false;
102857
- }
102581
+ if (!selector) return false;
102582
+ if (selector.includes("[data-composition-id=")) return false;
102583
+ if (selector.startsWith("#")) return false;
102858
102584
  return selector.startsWith(".") || /^[a-z]/i.test(selector);
102859
102585
  }
102860
102586
  function getSingleClassSelector(selector) {
102861
102587
  const match2 = selector.trim().match(/^\.(?<name>[A-Za-z0-9_-]+)$/);
102862
102588
  return match2?.groups?.name || null;
102863
102589
  }
102864
- function truncateSnippet(value, maxLength = 220) {
102865
- const normalized = value.replace(/\s+/g, " ").trim();
102866
- if (!normalized) {
102867
- return void 0;
102590
+ var gsapRules = [
102591
+ // overlapping_gsap_tweens + gsap_animates_clip_element + unscoped_gsap_selector
102592
+ ({ tags, scripts, rootCompositionId }) => {
102593
+ const findings = [];
102594
+ const clipIds = /* @__PURE__ */ new Map();
102595
+ const clipClasses = /* @__PURE__ */ new Map();
102596
+ for (const tag of tags) {
102597
+ const classAttr = readAttr(tag.raw, "class") || "";
102598
+ const classes = classAttr.split(/\s+/).filter(Boolean);
102599
+ if (!classes.includes("clip")) continue;
102600
+ const id = readAttr(tag.raw, "id");
102601
+ const info = {
102602
+ tag: tag.name,
102603
+ id: id || "",
102604
+ classes: classAttr
102605
+ };
102606
+ if (id) clipIds.set(`#${id}`, info);
102607
+ for (const cls of classes) {
102608
+ if (cls !== "clip") clipClasses.set(`.${cls}`, info);
102609
+ }
102610
+ }
102611
+ const classUsage = countClassUsage(tags);
102612
+ for (const script of scripts) {
102613
+ const localTimelineCompId = readRegisteredTimelineCompositionId(script.content);
102614
+ const gsapWindows = extractGsapWindows(script.content);
102615
+ for (let i = 0; i < gsapWindows.length; i++) {
102616
+ const left2 = gsapWindows[i];
102617
+ if (!left2) continue;
102618
+ if (left2.end <= left2.position) continue;
102619
+ for (let j = i + 1; j < gsapWindows.length; j++) {
102620
+ const right2 = gsapWindows[j];
102621
+ if (!right2) continue;
102622
+ if (right2.end <= right2.position) continue;
102623
+ if (left2.targetSelector !== right2.targetSelector) continue;
102624
+ const overlapStart = Math.max(left2.position, right2.position);
102625
+ const overlapEnd = Math.min(left2.end, right2.end);
102626
+ if (overlapEnd <= overlapStart) continue;
102627
+ if (left2.overwriteAuto || right2.overwriteAuto) continue;
102628
+ const sharedProperties = left2.properties.filter(
102629
+ (prop2) => right2.properties.includes(prop2)
102630
+ );
102631
+ if (sharedProperties.length === 0) continue;
102632
+ findings.push({
102633
+ code: "overlapping_gsap_tweens",
102634
+ severity: "warning",
102635
+ message: `GSAP tweens overlap on "${left2.targetSelector}" for ${sharedProperties.join(", ")} between ${overlapStart.toFixed(2)}s and ${overlapEnd.toFixed(2)}s.`,
102636
+ selector: left2.targetSelector,
102637
+ fixHint: 'Shorten the earlier tween, move the later tween, or add `overwrite: "auto"`.',
102638
+ snippet: truncateSnippet(`${left2.raw}
102639
+ ${right2.raw}`)
102640
+ });
102641
+ }
102642
+ }
102643
+ for (const win of gsapWindows) {
102644
+ const sel = win.targetSelector;
102645
+ const clipInfo = clipIds.get(sel) || clipClasses.get(sel);
102646
+ if (!clipInfo) continue;
102647
+ const elDesc = `<${clipInfo.tag}${clipInfo.id ? ` id="${clipInfo.id}"` : ""} class="${clipInfo.classes}">`;
102648
+ findings.push({
102649
+ code: "gsap_animates_clip_element",
102650
+ severity: "error",
102651
+ message: `GSAP animation targets a clip element. Selector "${sel}" resolves to element ${elDesc}. The framework manages clip visibility \u2014 animate an inner wrapper instead.`,
102652
+ selector: sel,
102653
+ elementId: clipInfo.id || void 0,
102654
+ fixHint: "Wrap content in a child <div> and target that with GSAP.",
102655
+ snippet: truncateSnippet(win.raw)
102656
+ });
102657
+ }
102658
+ if (!localTimelineCompId || localTimelineCompId === rootCompositionId) continue;
102659
+ for (const win of gsapWindows) {
102660
+ if (!isSuspiciousGlobalSelector(win.targetSelector)) continue;
102661
+ const className = getSingleClassSelector(win.targetSelector);
102662
+ if (className && (classUsage.get(className) || 0) < 2) continue;
102663
+ findings.push({
102664
+ code: "unscoped_gsap_selector",
102665
+ severity: "warning",
102666
+ message: `Timeline "${localTimelineCompId}" uses unscoped selector "${win.targetSelector}" that will target elements in ALL compositions when bundled, causing data loss (opacity, transforms, etc.).`,
102667
+ selector: win.targetSelector,
102668
+ fixHint: `Scope the selector: \`[data-composition-id="${localTimelineCompId}"] ${win.targetSelector}\` or use a unique id.`,
102669
+ snippet: truncateSnippet(win.raw)
102670
+ });
102671
+ }
102672
+ }
102673
+ return findings;
102674
+ },
102675
+ // gsap_css_transform_conflict
102676
+ ({ styles, scripts }) => {
102677
+ const findings = [];
102678
+ const cssTranslateSelectors = /* @__PURE__ */ new Map();
102679
+ const cssScaleSelectors = /* @__PURE__ */ new Map();
102680
+ for (const style of styles) {
102681
+ for (const [, selector, body] of style.content.matchAll(
102682
+ /([#.][a-zA-Z0-9_-]+)\s*\{([^}]+)\}/g
102683
+ )) {
102684
+ const tMatch = body?.match(/transform\s*:\s*([^;]+)/);
102685
+ if (!tMatch || !tMatch[1]) continue;
102686
+ const transformVal = tMatch[1].trim();
102687
+ if (/translate/i.test(transformVal))
102688
+ cssTranslateSelectors.set((selector ?? "").trim(), transformVal);
102689
+ if (/scale/i.test(transformVal))
102690
+ cssScaleSelectors.set((selector ?? "").trim(), transformVal);
102691
+ }
102692
+ }
102693
+ if (cssTranslateSelectors.size === 0 && cssScaleSelectors.size === 0) return findings;
102694
+ for (const script of scripts) {
102695
+ if (!/gsap\.timeline/.test(script.content)) continue;
102696
+ const windows = extractGsapWindows(script.content);
102697
+ const conflicts = /* @__PURE__ */ new Map();
102698
+ for (const win of windows) {
102699
+ if (win.method === "fromTo") continue;
102700
+ const sel = win.targetSelector;
102701
+ const cssKey = sel.startsWith("#") || sel.startsWith(".") ? sel : `#${sel}`;
102702
+ const translateProps = win.properties.filter(
102703
+ (p) => ["x", "y", "xPercent", "yPercent"].includes(p)
102704
+ );
102705
+ const scaleProps = win.properties.filter((p) => p === "scale");
102706
+ const cssFromTranslate = translateProps.length > 0 ? cssTranslateSelectors.get(cssKey) : void 0;
102707
+ const cssFromScale = scaleProps.length > 0 ? cssScaleSelectors.get(cssKey) : void 0;
102708
+ if (!cssFromTranslate && !cssFromScale) continue;
102709
+ const existing = conflicts.get(sel) ?? {
102710
+ cssTransform: [cssFromTranslate, cssFromScale].filter(Boolean).join(" "),
102711
+ props: /* @__PURE__ */ new Set(),
102712
+ raw: win.raw
102713
+ };
102714
+ for (const p of [...translateProps, ...scaleProps]) existing.props.add(p);
102715
+ conflicts.set(sel, existing);
102716
+ }
102717
+ for (const [sel, { cssTransform, props, raw: raw2 }] of conflicts) {
102718
+ const propList = [...props].join("/");
102719
+ findings.push({
102720
+ code: "gsap_css_transform_conflict",
102721
+ severity: "warning",
102722
+ message: `"${sel}" has CSS \`transform: ${cssTransform}\` and a GSAP tween animates ${propList}. GSAP will overwrite the full CSS transform, discarding any translateX(-50%) centering or CSS scale value.`,
102723
+ selector: sel,
102724
+ fixHint: `Remove the transform from CSS and use tl.fromTo('${sel}', { xPercent: -50, x: -1000 }, { xPercent: -50, x: 0 }) so GSAP owns the full transform state. tl.fromTo is exempt from this rule.`,
102725
+ snippet: truncateSnippet(raw2)
102726
+ });
102727
+ }
102728
+ }
102729
+ return findings;
102730
+ },
102731
+ // missing_gsap_script
102732
+ ({ scripts }) => {
102733
+ const allScriptTexts = scripts.filter((s) => !/\bsrc\s*=/.test(s.attrs)).map((s) => s.content);
102734
+ const allScriptSrcs = scripts.map((s) => readAttr(`<script ${s.attrs}>`, "src") || "").filter(Boolean);
102735
+ const usesGsap = allScriptTexts.some(
102736
+ (t) => /gsap\.(to|from|fromTo|timeline|set|registerPlugin)\b/.test(t)
102737
+ );
102738
+ const hasGsapScript = allScriptSrcs.some((src) => /gsap/i.test(src));
102739
+ if (!usesGsap || hasGsapScript) return [];
102740
+ return [
102741
+ {
102742
+ code: "missing_gsap_script",
102743
+ severity: "error",
102744
+ message: "Composition uses GSAP but no GSAP script is loaded. The animation will not run.",
102745
+ fixHint: 'Add <script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js"></script> before your animation script.'
102746
+ }
102747
+ ];
102868
102748
  }
102869
- if (normalized.length <= maxLength) {
102870
- return normalized;
102749
+ ];
102750
+
102751
+ // ../core/src/lint/rules/captions.ts
102752
+ var captionRules = [
102753
+ // caption_exit_missing_hard_kill
102754
+ ({ scripts }) => {
102755
+ const findings = [];
102756
+ for (const script of scripts) {
102757
+ const content = script.content;
102758
+ const hasExitTween = /\.to\s*\([^,]+,\s*\{[^}]*opacity\s*:\s*0/.test(content);
102759
+ const hasHardKill = /\.set\s*\([^,]+,\s*\{[^}]*(?:visibility\s*:\s*["']hidden["']|opacity\s*:\s*0)/.test(
102760
+ content
102761
+ );
102762
+ const hasCaptionLoop = /forEach|\.forEach\s*\(/.test(content) && /createElement|caption|group|cg-/.test(content);
102763
+ if (hasCaptionLoop && hasExitTween && !hasHardKill) {
102764
+ findings.push({
102765
+ code: "caption_exit_missing_hard_kill",
102766
+ severity: "warning",
102767
+ message: "Caption exit animations (tl.to with opacity: 0) detected without a hard tl.set kill. Exit tweens can fail when karaoke word-level tweens conflict, leaving captions stuck on screen.",
102768
+ fixHint: 'Add `tl.set(groupEl, { opacity: 0, visibility: "hidden" }, group.end)` after every exit tl.to animation as a deterministic kill.'
102769
+ });
102770
+ }
102771
+ }
102772
+ return findings;
102773
+ },
102774
+ // caption_text_overflow_risk
102775
+ ({ styles }) => {
102776
+ const findings = [];
102777
+ for (const style of styles) {
102778
+ const captionBlocks = style.content.matchAll(
102779
+ /(\.caption[-_]?(?:group|container|text|line|word)|#caption[-_]?container)\s*\{([^}]+)\}/gi
102780
+ );
102781
+ for (const [, selector, body] of captionBlocks) {
102782
+ if (!body) continue;
102783
+ const hasNowrap = /white-space\s*:\s*nowrap/i.test(body);
102784
+ const hasMaxWidth = /max-width/i.test(body);
102785
+ if (hasNowrap && !hasMaxWidth) {
102786
+ findings.push({
102787
+ code: "caption_text_overflow_risk",
102788
+ severity: "warning",
102789
+ selector: (selector ?? "").trim(),
102790
+ message: `Caption selector "${(selector ?? "").trim()}" has white-space: nowrap but no max-width. Long phrases will clip off-screen.`,
102791
+ fixHint: "Add max-width: 1600px (landscape) or max-width: 900px (portrait) and overflow: hidden."
102792
+ });
102793
+ }
102794
+ }
102795
+ }
102796
+ return findings;
102797
+ },
102798
+ // caption_container_relative_position
102799
+ ({ styles }) => {
102800
+ const findings = [];
102801
+ for (const style of styles) {
102802
+ const captionBlocks = style.content.matchAll(
102803
+ /(\.caption[-_]?(?:group|container|text|line)|#caption[-_]?container)\s*\{([^}]+)\}/gi
102804
+ );
102805
+ for (const [, selector, body] of captionBlocks) {
102806
+ if (!body) continue;
102807
+ if (/position\s*:\s*relative/i.test(body)) {
102808
+ findings.push({
102809
+ code: "caption_container_relative_position",
102810
+ severity: "warning",
102811
+ selector: (selector ?? "").trim(),
102812
+ message: `Caption selector "${(selector ?? "").trim()}" uses position: relative which causes overflow and breaks caption stacking.`,
102813
+ fixHint: "Use position: absolute for all caption elements."
102814
+ });
102815
+ }
102816
+ }
102817
+ }
102818
+ return findings;
102819
+ }
102820
+ ];
102821
+
102822
+ // ../core/src/lint/rules/composition.ts
102823
+ var compositionRules = [
102824
+ // timed_element_missing_visibility_hidden
102825
+ ({ tags }) => {
102826
+ const findings = [];
102827
+ for (const tag of tags) {
102828
+ if (tag.name === "audio" || tag.name === "script" || tag.name === "style") continue;
102829
+ if (!readAttr(tag.raw, "data-start")) continue;
102830
+ if (readAttr(tag.raw, "data-composition-id")) continue;
102831
+ if (readAttr(tag.raw, "data-composition-src")) continue;
102832
+ const classAttr = readAttr(tag.raw, "class") || "";
102833
+ const styleAttr = readAttr(tag.raw, "style") || "";
102834
+ const hasClip = classAttr.split(/\s+/).includes("clip");
102835
+ const hasHiddenStyle = /visibility\s*:\s*hidden/i.test(styleAttr) || /opacity\s*:\s*0/i.test(styleAttr);
102836
+ if (!hasClip && !hasHiddenStyle) {
102837
+ const elementId = readAttr(tag.raw, "id") || void 0;
102838
+ findings.push({
102839
+ code: "timed_element_missing_visibility_hidden",
102840
+ severity: "info",
102841
+ message: `<${tag.name}${elementId ? ` id="${elementId}"` : ""}> has data-start but no class="clip", visibility:hidden, or opacity:0. Consider adding initial hidden state if the element should not be visible before its start time.`,
102842
+ elementId,
102843
+ fixHint: 'Add class="clip" (with CSS: .clip { visibility: hidden; }) or style="opacity:0" if the element should start hidden.',
102844
+ snippet: truncateSnippet(tag.raw)
102845
+ });
102846
+ }
102847
+ }
102848
+ return findings;
102849
+ },
102850
+ // deprecated_data_layer + deprecated_data_end
102851
+ ({ tags }) => {
102852
+ const findings = [];
102853
+ for (const tag of tags) {
102854
+ if (readAttr(tag.raw, "data-layer") && !readAttr(tag.raw, "data-track-index")) {
102855
+ const elementId = readAttr(tag.raw, "id") || void 0;
102856
+ findings.push({
102857
+ code: "deprecated_data_layer",
102858
+ severity: "warning",
102859
+ message: `<${tag.name}${elementId ? ` id="${elementId}"` : ""}> uses data-layer instead of data-track-index.`,
102860
+ elementId,
102861
+ fixHint: "Replace data-layer with data-track-index. The runtime reads data-track-index.",
102862
+ snippet: truncateSnippet(tag.raw)
102863
+ });
102864
+ }
102865
+ if (readAttr(tag.raw, "data-end") && !readAttr(tag.raw, "data-duration")) {
102866
+ const elementId = readAttr(tag.raw, "id") || void 0;
102867
+ findings.push({
102868
+ code: "deprecated_data_end",
102869
+ severity: "warning",
102870
+ message: `<${tag.name}${elementId ? ` id="${elementId}"` : ""}> uses data-end without data-duration. Use data-duration in source HTML.`,
102871
+ elementId,
102872
+ fixHint: "Replace data-end with data-duration. The compiler generates data-end from data-duration automatically.",
102873
+ snippet: truncateSnippet(tag.raw)
102874
+ });
102875
+ }
102876
+ }
102877
+ return findings;
102878
+ },
102879
+ // template_literal_selector
102880
+ ({ scripts }) => {
102881
+ const findings = [];
102882
+ for (const script of scripts) {
102883
+ const templateLiteralSelectorPattern = /(?:querySelector|querySelectorAll)\s*\(\s*`[^`]*\$\{[^}]+\}[^`]*`\s*\)/g;
102884
+ let tlMatch;
102885
+ while ((tlMatch = templateLiteralSelectorPattern.exec(script.content)) !== null) {
102886
+ findings.push({
102887
+ code: "template_literal_selector",
102888
+ severity: "error",
102889
+ message: "querySelector uses a template literal variable (e.g. `${compId}`). The HTML bundler's CSS parser crashes on these. Use a hardcoded string instead.",
102890
+ fixHint: "Replace the template literal variable with a hardcoded string. The bundler's CSS parser cannot handle interpolated variables in script content.",
102891
+ snippet: truncateSnippet(tlMatch[0])
102892
+ });
102893
+ }
102894
+ }
102895
+ return findings;
102896
+ },
102897
+ // external_script_dependency
102898
+ ({ source: source2 }) => {
102899
+ const findings = [];
102900
+ const externalScriptRe = /<script\b[^>]*\bsrc=["'](https?:\/\/[^"']+)["'][^>]*>/gi;
102901
+ let match2;
102902
+ const seen = /* @__PURE__ */ new Set();
102903
+ while ((match2 = externalScriptRe.exec(source2)) !== null) {
102904
+ const src = match2[1] ?? "";
102905
+ if (seen.has(src)) continue;
102906
+ seen.add(src);
102907
+ findings.push({
102908
+ code: "external_script_dependency",
102909
+ severity: "info",
102910
+ message: `This composition loads an external script from \`${src}\`. The HyperFrames bundler automatically hoists CDN scripts from sub-compositions into the parent document. In unbundled runtime mode, \`loadExternalCompositions\` re-injects them. If you're using a custom pipeline that bypasses both, you'll need to include this script manually.`,
102911
+ fixHint: "No action needed when using `hyperframes preview` or `hyperframes render`. If using a custom pipeline, add this script tag to your root composition or HTML page.",
102912
+ snippet: truncateSnippet(match2[0] ?? "")
102913
+ });
102914
+ }
102915
+ return findings;
102916
+ }
102917
+ ];
102918
+
102919
+ // ../core/src/lint/rules/adapters.ts
102920
+ var adapterRules = [
102921
+ // missing_lottie_script
102922
+ ({ tags, scripts }) => {
102923
+ const allScriptTexts = scripts.filter((s) => !/\bsrc\s*=/.test(s.attrs)).map((s) => s.content);
102924
+ const allScriptSrcs = scripts.map((s) => readAttr(`<script ${s.attrs}>`, "src") || "").filter(Boolean);
102925
+ const hasLottieAttr = tags.some((t) => readAttr(t.raw, "data-lottie-src") !== null);
102926
+ const usesLottieApi = allScriptTexts.some(
102927
+ (t) => /lottie\.(loadAnimation|setSpeed|play|stop|destroy)\b/.test(t)
102928
+ );
102929
+ const hasLottieScript = allScriptSrcs.some((src) => /lottie/i.test(src));
102930
+ if (!(hasLottieAttr || usesLottieApi) || hasLottieScript) return [];
102931
+ return [
102932
+ {
102933
+ code: "missing_lottie_script",
102934
+ severity: "error",
102935
+ message: "Composition uses Lottie but no Lottie script is loaded. The animation will not render.",
102936
+ fixHint: 'Add <script src="https://cdn.jsdelivr.net/npm/lottie-web@5/build/player/lottie.min.js"></script> before your Lottie code.'
102937
+ }
102938
+ ];
102939
+ },
102940
+ // missing_three_script
102941
+ ({ scripts }) => {
102942
+ const allScriptTexts = scripts.filter((s) => !/\bsrc\s*=/.test(s.attrs)).map((s) => s.content);
102943
+ const allScriptSrcs = scripts.map((s) => readAttr(`<script ${s.attrs}>`, "src") || "").filter(Boolean);
102944
+ const usesThree = allScriptTexts.some((t) => /\bTHREE\./.test(t));
102945
+ const hasThreeScript = allScriptSrcs.some((src) => /three/i.test(src));
102946
+ if (!usesThree || hasThreeScript) return [];
102947
+ return [
102948
+ {
102949
+ code: "missing_three_script",
102950
+ severity: "error",
102951
+ message: "Composition uses Three.js but no Three.js script is loaded. The 3D scene will not render.",
102952
+ fixHint: 'Add <script src="https://cdn.jsdelivr.net/npm/three@0.160/build/three.min.js"></script> before your Three.js code.'
102953
+ }
102954
+ ];
102955
+ }
102956
+ ];
102957
+
102958
+ // ../core/src/lint/hyperframeLinter.ts
102959
+ var ALL_RULES = [
102960
+ ...coreRules,
102961
+ ...mediaRules,
102962
+ ...gsapRules,
102963
+ ...captionRules,
102964
+ ...compositionRules,
102965
+ ...adapterRules
102966
+ ];
102967
+ function lintHyperframeHtml(html, options = {}) {
102968
+ const ctx = buildLintContext(html, options);
102969
+ const findings = [];
102970
+ const seen = /* @__PURE__ */ new Set();
102971
+ for (const rule of ALL_RULES) {
102972
+ for (const finding of rule(ctx)) {
102973
+ const dedupeKey = [
102974
+ finding.code,
102975
+ finding.severity,
102976
+ finding.selector || "",
102977
+ finding.elementId || "",
102978
+ finding.message
102979
+ ].join("|");
102980
+ if (seen.has(dedupeKey)) continue;
102981
+ seen.add(dedupeKey);
102982
+ findings.push(options.filePath ? { ...finding, file: options.filePath } : finding);
102983
+ }
102984
+ }
102985
+ const errorCount = findings.filter((f) => f.severity === "error").length;
102986
+ const warningCount = findings.filter((f) => f.severity === "warning").length;
102987
+ const infoCount = findings.filter((f) => f.severity === "info").length;
102988
+ return {
102989
+ ok: errorCount === 0,
102990
+ errorCount,
102991
+ warningCount,
102992
+ infoCount,
102993
+ findings
102994
+ };
102995
+ }
102996
+
102997
+ // ../core/src/compiler/rewriteSubCompPaths.ts
102998
+ import { join as join4, resolve as resolve6, dirname as dirname4 } from "path";
102999
+ var PATH_ATTRS = ["src", "href"];
103000
+ function isAbsoluteOrSpecial(val) {
103001
+ return !val || val.startsWith("http://") || val.startsWith("https://") || val.startsWith("//") || val.startsWith("data:") || val.startsWith("#");
103002
+ }
103003
+ function needsRewrite(val) {
103004
+ return val.startsWith("../") || val === "..";
103005
+ }
103006
+ function rewriteAssetPaths(elements, compSrcPath, getAttr2, setAttr) {
103007
+ const compDir = dirname4(compSrcPath);
103008
+ if (!compDir || compDir === ".") return;
103009
+ for (const el of elements) {
103010
+ for (const attr of PATH_ATTRS) {
103011
+ const val = (getAttr2(el, attr) || "").trim();
103012
+ if (isAbsoluteOrSpecial(val)) continue;
103013
+ if (!needsRewrite(val)) continue;
103014
+ const rewritten = join4(compDir, val);
103015
+ const normalized = resolve6("/", rewritten).slice(1);
103016
+ if (normalized !== val) {
103017
+ setAttr(el, attr, normalized);
103018
+ }
103019
+ }
102871
103020
  }
102872
- return `${normalized.slice(0, maxLength - 3)}...`;
102873
103021
  }
102874
103022
 
102875
103023
  // ../core/src/inline-scripts/hyperframesRuntime.engine.ts
@@ -103237,9 +103385,9 @@ async function initializeSession(session) {
103237
103385
  }
103238
103386
  async function captureFrameErrorDiagnostics(session, frameIndex, time, error) {
103239
103387
  try {
103240
- const diagnosticsDir = join4(session.outputDir, "diagnostics");
103388
+ const diagnosticsDir = join5(session.outputDir, "diagnostics");
103241
103389
  if (!existsSync4(diagnosticsDir)) mkdirSync(diagnosticsDir, { recursive: true });
103242
- const base = join4(diagnosticsDir, `frame-error-${frameIndex}`);
103390
+ const base = join5(diagnosticsDir, `frame-error-${frameIndex}`);
103243
103391
  await session.page.screenshot({ path: `${base}.png`, type: "png", fullPage: true });
103244
103392
  const html = await session.page.content();
103245
103393
  writeFileSync(`${base}.html`, html, "utf-8");
@@ -103337,7 +103485,7 @@ async function captureFrame(session, frameIndex, time) {
103337
103485
  );
103338
103486
  const ext = options.format === "png" ? "png" : "jpg";
103339
103487
  const frameName = `frame_${String(frameIndex).padStart(6, "0")}.${ext}`;
103340
- const framePath = join4(outputDir, frameName);
103488
+ const framePath = join5(outputDir, frameName);
103341
103489
  writeFileSync(framePath, buffer);
103342
103490
  return { frameIndex, time: quantizedTime, path: framePath, captureTimeMs };
103343
103491
  }
@@ -103387,12 +103535,12 @@ function getCapturePerfSummary(session) {
103387
103535
  // ../engine/src/services/chunkEncoder.ts
103388
103536
  import { spawn as spawn5 } from "child_process";
103389
103537
  import { copyFileSync, existsSync as existsSync5, mkdirSync as mkdirSync2, readdirSync as readdirSync3, statSync as statSync3, writeFileSync as writeFileSync2 } from "fs";
103390
- import { join as join5, dirname as dirname4 } from "path";
103538
+ import { join as join6, dirname as dirname5 } from "path";
103391
103539
 
103392
103540
  // ../engine/src/utils/gpuEncoder.ts
103393
103541
  import { spawn as spawn3 } from "child_process";
103394
103542
  async function detectGpuEncoder() {
103395
- return new Promise((resolve12) => {
103543
+ return new Promise((resolve13) => {
103396
103544
  const ffmpeg = spawn3("ffmpeg", ["-encoders"], {
103397
103545
  stdio: ["pipe", "pipe", "pipe"]
103398
103546
  });
@@ -103401,13 +103549,13 @@ async function detectGpuEncoder() {
103401
103549
  stdout += data.toString();
103402
103550
  });
103403
103551
  ffmpeg.on("close", () => {
103404
- if (stdout.includes("h264_nvenc")) resolve12("nvenc");
103405
- else if (stdout.includes("h264_videotoolbox")) resolve12("videotoolbox");
103406
- else if (stdout.includes("h264_vaapi")) resolve12("vaapi");
103407
- else if (stdout.includes("h264_qsv")) resolve12("qsv");
103408
- else resolve12(null);
103552
+ if (stdout.includes("h264_nvenc")) resolve13("nvenc");
103553
+ else if (stdout.includes("h264_videotoolbox")) resolve13("videotoolbox");
103554
+ else if (stdout.includes("h264_vaapi")) resolve13("vaapi");
103555
+ else if (stdout.includes("h264_qsv")) resolve13("qsv");
103556
+ else resolve13(null);
103409
103557
  });
103410
- ffmpeg.on("error", () => resolve12(null));
103558
+ ffmpeg.on("error", () => resolve13(null));
103411
103559
  });
103412
103560
  }
103413
103561
  var cachedGpuEncoder = void 0;
@@ -103441,7 +103589,7 @@ async function runFfmpeg(args, opts) {
103441
103589
  const signal = opts?.signal;
103442
103590
  const timeout2 = opts?.timeout ?? DEFAULT_TIMEOUT2;
103443
103591
  const onStderr = opts?.onStderr;
103444
- return new Promise((resolve12) => {
103592
+ return new Promise((resolve13) => {
103445
103593
  const ffmpeg = spawn4("ffmpeg", args);
103446
103594
  let stderr = "";
103447
103595
  const onAbort = () => {
@@ -103467,7 +103615,7 @@ async function runFfmpeg(args, opts) {
103467
103615
  ffmpeg.on("close", (code) => {
103468
103616
  clearTimeout(timer2);
103469
103617
  if (signal) signal.removeEventListener("abort", onAbort);
103470
- resolve12({
103618
+ resolve13({
103471
103619
  success: !signal?.aborted && code === 0,
103472
103620
  exitCode: code,
103473
103621
  stderr,
@@ -103477,7 +103625,7 @@ async function runFfmpeg(args, opts) {
103477
103625
  ffmpeg.on("error", (err) => {
103478
103626
  clearTimeout(timer2);
103479
103627
  if (signal) signal.removeEventListener("abort", onAbort);
103480
- resolve12({
103628
+ resolve13({
103481
103629
  success: false,
103482
103630
  exitCode: null,
103483
103631
  stderr: err.message,
@@ -103573,7 +103721,7 @@ function buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder = null) {
103573
103721
  }
103574
103722
  async function encodeFramesFromDir(framesDir, framePattern, outputPath, options, signal, config2) {
103575
103723
  const startTime = Date.now();
103576
- const outputDir = dirname4(outputPath);
103724
+ const outputDir = dirname5(outputPath);
103577
103725
  if (!existsSync5(outputDir)) mkdirSync2(outputDir, { recursive: true });
103578
103726
  const files = readdirSync3(framesDir).filter((f) => f.match(/\.(jpg|jpeg|png)$/i));
103579
103727
  const frameCount = files.length;
@@ -103591,10 +103739,10 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
103591
103739
  if (options.useGpu) {
103592
103740
  gpuEncoder = await getCachedGpuEncoder();
103593
103741
  }
103594
- const inputPath = join5(framesDir, framePattern);
103742
+ const inputPath = join6(framesDir, framePattern);
103595
103743
  const inputArgs = ["-framerate", String(options.fps), "-i", inputPath];
103596
103744
  const args = buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder);
103597
- return new Promise((resolve12) => {
103745
+ return new Promise((resolve13) => {
103598
103746
  const ffmpeg = spawn5("ffmpeg", args);
103599
103747
  let stderr = "";
103600
103748
  const onAbort = () => {
@@ -103619,7 +103767,7 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
103619
103767
  if (signal) signal.removeEventListener("abort", onAbort);
103620
103768
  const durationMs = Date.now() - startTime;
103621
103769
  if (signal?.aborted) {
103622
- resolve12({
103770
+ resolve13({
103623
103771
  success: false,
103624
103772
  outputPath,
103625
103773
  durationMs,
@@ -103630,7 +103778,7 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
103630
103778
  return;
103631
103779
  }
103632
103780
  if (code !== 0) {
103633
- resolve12({
103781
+ resolve13({
103634
103782
  success: false,
103635
103783
  outputPath,
103636
103784
  durationMs,
@@ -103641,12 +103789,12 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
103641
103789
  return;
103642
103790
  }
103643
103791
  const fileSize = existsSync5(outputPath) ? statSync3(outputPath).size : 0;
103644
- resolve12({ success: true, outputPath, durationMs, framesEncoded: frameCount, fileSize });
103792
+ resolve13({ success: true, outputPath, durationMs, framesEncoded: frameCount, fileSize });
103645
103793
  });
103646
103794
  ffmpeg.on("error", (err) => {
103647
103795
  clearTimeout(timer2);
103648
103796
  if (signal) signal.removeEventListener("abort", onAbort);
103649
- resolve12({
103797
+ resolve13({
103650
103798
  success: false,
103651
103799
  outputPath,
103652
103800
  durationMs: Date.now() - startTime,
@@ -103672,7 +103820,7 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
103672
103820
  }
103673
103821
  const chunkSize = Math.max(30, Math.floor(chunkSizeFrames));
103674
103822
  const chunkCount = Math.ceil(files.length / chunkSize);
103675
- const chunkDir = join5(dirname4(outputPath), "chunk-encode");
103823
+ const chunkDir = join6(dirname5(outputPath), "chunk-encode");
103676
103824
  if (!existsSync5(chunkDir)) mkdirSync2(chunkDir, { recursive: true });
103677
103825
  const chunkPaths = [];
103678
103826
  for (let i = 0; i < chunkCount; i++) {
@@ -103689,8 +103837,8 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
103689
103837
  const startNumber = i * chunkSize;
103690
103838
  const framesInChunk = Math.min(chunkSize, files.length - startNumber);
103691
103839
  const ext = outputPath.endsWith(".webm") ? ".webm" : ".mp4";
103692
- const chunkPath = join5(chunkDir, `chunk_${String(i).padStart(4, "0")}${ext}`);
103693
- const inputPath = join5(framesDir, framePattern);
103840
+ const chunkPath = join6(chunkDir, `chunk_${String(i).padStart(4, "0")}${ext}`);
103841
+ const inputPath = join6(framesDir, framePattern);
103694
103842
  const inputArgs = [
103695
103843
  "-framerate",
103696
103844
  String(options.fps),
@@ -103704,18 +103852,18 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
103704
103852
  let gpuEncoder = null;
103705
103853
  if (options.useGpu) gpuEncoder = await getCachedGpuEncoder();
103706
103854
  const args = buildEncoderArgs(options, inputArgs, chunkPath, gpuEncoder);
103707
- const chunkResult = await new Promise((resolve12) => {
103855
+ const chunkResult = await new Promise((resolve13) => {
103708
103856
  const ffmpeg = spawn5("ffmpeg", args);
103709
103857
  let stderr = "";
103710
103858
  ffmpeg.stderr.on("data", (d) => {
103711
103859
  stderr += d.toString();
103712
103860
  });
103713
103861
  ffmpeg.on("close", (code) => {
103714
- if (code === 0) resolve12({ success: true });
103715
- else resolve12({ success: false, error: `Chunk ${i} encode failed: ${stderr.slice(-400)}` });
103862
+ if (code === 0) resolve13({ success: true });
103863
+ else resolve13({ success: false, error: `Chunk ${i} encode failed: ${stderr.slice(-400)}` });
103716
103864
  });
103717
103865
  ffmpeg.on("error", (err) => {
103718
- resolve12({ success: false, error: `Chunk ${i} encode error: ${err.message}` });
103866
+ resolve13({ success: false, error: `Chunk ${i} encode error: ${err.message}` });
103719
103867
  });
103720
103868
  });
103721
103869
  if (!chunkResult.success) {
@@ -103730,7 +103878,7 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
103730
103878
  }
103731
103879
  chunkPaths.push(chunkPath);
103732
103880
  }
103733
- const concatListPath = join5(chunkDir, "concat-list.txt");
103881
+ const concatListPath = join6(chunkDir, "concat-list.txt");
103734
103882
  const concatInput = chunkPaths.map((path12) => `file '${path12.replace(/'/g, "'\\''")}'`).join("\n");
103735
103883
  writeFileSync2(concatListPath, concatInput, "utf-8");
103736
103884
  const concatArgs = [
@@ -103745,18 +103893,18 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
103745
103893
  "-y",
103746
103894
  outputPath
103747
103895
  ];
103748
- const concatResult = await new Promise((resolve12) => {
103896
+ const concatResult = await new Promise((resolve13) => {
103749
103897
  const ffmpeg = spawn5("ffmpeg", concatArgs);
103750
103898
  let stderr = "";
103751
103899
  ffmpeg.stderr.on("data", (d) => {
103752
103900
  stderr += d.toString();
103753
103901
  });
103754
103902
  ffmpeg.on("close", (code) => {
103755
- if (code === 0) resolve12({ success: true });
103756
- else resolve12({ success: false, error: `Chunk concat failed: ${stderr.slice(-400)}` });
103903
+ if (code === 0) resolve13({ success: true });
103904
+ else resolve13({ success: false, error: `Chunk concat failed: ${stderr.slice(-400)}` });
103757
103905
  });
103758
103906
  ffmpeg.on("error", (err) => {
103759
- resolve12({ success: false, error: `Chunk concat error: ${err.message}` });
103907
+ resolve13({ success: false, error: `Chunk concat error: ${err.message}` });
103760
103908
  });
103761
103909
  });
103762
103910
  if (!concatResult.success) {
@@ -103779,7 +103927,7 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
103779
103927
  };
103780
103928
  }
103781
103929
  async function muxVideoWithAudio(videoPath, audioPath, outputPath, signal, config2) {
103782
- const outputDir = dirname4(outputPath);
103930
+ const outputDir = dirname5(outputPath);
103783
103931
  if (!existsSync5(outputDir)) mkdirSync2(outputDir, { recursive: true });
103784
103932
  const isWebm = outputPath.endsWith(".webm");
103785
103933
  const args = ["-i", videoPath, "-i", audioPath, "-c:v", "copy"];
@@ -103833,7 +103981,7 @@ async function applyFaststart(inputPath, outputPath, signal, config2) {
103833
103981
  // ../engine/src/services/streamingEncoder.ts
103834
103982
  import { spawn as spawn6 } from "child_process";
103835
103983
  import { existsSync as existsSync6, mkdirSync as mkdirSync3, statSync as statSync4 } from "fs";
103836
- import { dirname as dirname5 } from "path";
103984
+ import { dirname as dirname6 } from "path";
103837
103985
  function createFrameReorderBuffer(startFrame, endFrame) {
103838
103986
  let nextFrame = startFrame;
103839
103987
  let waiters = [];
@@ -103846,16 +103994,16 @@ function createFrameReorderBuffer(startFrame, endFrame) {
103846
103994
  }
103847
103995
  };
103848
103996
  return {
103849
- waitForFrame: (frame) => new Promise((resolve12) => {
103850
- waiters.push({ frame, resolve: resolve12 });
103997
+ waitForFrame: (frame) => new Promise((resolve13) => {
103998
+ waiters.push({ frame, resolve: resolve13 });
103851
103999
  resolveWaiters();
103852
104000
  }),
103853
104001
  advanceTo: (frame) => {
103854
104002
  nextFrame = frame;
103855
104003
  resolveWaiters();
103856
104004
  },
103857
- waitForAllDone: () => new Promise((resolve12) => {
103858
- waiters.push({ frame: endFrame, resolve: resolve12 });
104005
+ waitForAllDone: () => new Promise((resolve13) => {
104006
+ waiters.push({ frame: endFrame, resolve: resolve13 });
103859
104007
  resolveWaiters();
103860
104008
  })
103861
104009
  };
@@ -103940,7 +104088,7 @@ function buildStreamingArgs(options, outputPath, gpuEncoder = null) {
103940
104088
  return args;
103941
104089
  }
103942
104090
  async function spawnStreamingEncoder(outputPath, options, signal, config2) {
103943
- const outputDir = dirname5(outputPath);
104091
+ const outputDir = dirname6(outputPath);
103944
104092
  if (!existsSync6(outputDir)) mkdirSync3(outputDir, { recursive: true });
103945
104093
  let gpuEncoder = null;
103946
104094
  if (options.useGpu) {
@@ -103955,7 +104103,7 @@ async function spawnStreamingEncoder(outputPath, options, signal, config2) {
103955
104103
  let stderr = "";
103956
104104
  let exitCode = null;
103957
104105
  let exitPromiseResolve = null;
103958
- const exitPromise = new Promise((resolve12) => exitPromiseResolve = resolve12);
104106
+ const exitPromise = new Promise((resolve13) => exitPromiseResolve = resolve13);
103959
104107
  ffmpeg.stderr?.on("data", (data) => {
103960
104108
  stderr += data.toString();
103961
104109
  });
@@ -103999,8 +104147,8 @@ Process error: ${err.message}`;
103999
104147
  clearTimeout(timer2);
104000
104148
  if (signal) signal.removeEventListener("abort", onAbort);
104001
104149
  if (ffmpeg.stdin && !ffmpeg.stdin.destroyed) {
104002
- await new Promise((resolve12) => {
104003
- ffmpeg.stdin.end(() => resolve12());
104150
+ await new Promise((resolve13) => {
104151
+ ffmpeg.stdin.end(() => resolve13());
104004
104152
  });
104005
104153
  }
104006
104154
  await exitPromise;
@@ -104032,12 +104180,12 @@ Process error: ${err.message}`;
104032
104180
  // ../engine/src/services/videoFrameExtractor.ts
104033
104181
  import { spawn as spawn8 } from "child_process";
104034
104182
  import { existsSync as existsSync8, mkdirSync as mkdirSync5, readdirSync as readdirSync4, rmSync } from "fs";
104035
- import { join as join7 } from "path";
104183
+ import { join as join8 } from "path";
104036
104184
 
104037
104185
  // ../engine/src/utils/ffprobe.ts
104038
104186
  import { spawn as spawn7 } from "child_process";
104039
104187
  function runFfprobe(args) {
104040
- return new Promise((resolve12, reject) => {
104188
+ return new Promise((resolve13, reject) => {
104041
104189
  const proc = spawn7("ffprobe", args);
104042
104190
  let stdout = "";
104043
104191
  let stderr = "";
@@ -104051,7 +104199,7 @@ function runFfprobe(args) {
104051
104199
  if (code !== 0) {
104052
104200
  reject(new Error(`[FFmpeg] ffprobe exited with code ${code}: ${stderr}`));
104053
104201
  } else {
104054
- resolve12(stdout);
104202
+ resolve13(stdout);
104055
104203
  }
104056
104204
  });
104057
104205
  proc.on("error", (err) => {
@@ -104210,7 +104358,7 @@ async function analyzeKeyframeIntervalsUncached(filePath) {
104210
104358
  // ../engine/src/utils/urlDownloader.ts
104211
104359
  import { createWriteStream as createWriteStream2, existsSync as existsSync7, mkdirSync as mkdirSync4 } from "fs";
104212
104360
  import { createHash } from "crypto";
104213
- import { join as join6, extname as extname2 } from "path";
104361
+ import { join as join7, extname as extname2 } from "path";
104214
104362
  import { Readable as Readable2 } from "stream";
104215
104363
  import { finished } from "stream/promises";
104216
104364
  var downloadPathCache = /* @__PURE__ */ new Map();
@@ -104234,7 +104382,7 @@ async function downloadToTemp(url, destDir, timeoutMs = 3e5) {
104234
104382
  mkdirSync4(destDir, { recursive: true });
104235
104383
  }
104236
104384
  const filename = getFilenameFromUrl(url);
104237
- const localPath = join6(destDir, filename);
104385
+ const localPath = join7(destDir, filename);
104238
104386
  if (existsSync7(localPath)) {
104239
104387
  downloadPathCache.set(url, localPath);
104240
104388
  return localPath;
@@ -104318,11 +104466,11 @@ function parseVideoElements(html) {
104318
104466
  async function extractVideoFramesRange(videoPath, videoId, startTime, duration, options, signal, config2) {
104319
104467
  const ffmpegProcessTimeout = config2?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
104320
104468
  const { fps, outputDir, quality = 95, format: format3 = "jpg" } = options;
104321
- const videoOutputDir = join7(outputDir, videoId);
104469
+ const videoOutputDir = join8(outputDir, videoId);
104322
104470
  if (!existsSync8(videoOutputDir)) mkdirSync5(videoOutputDir, { recursive: true });
104323
104471
  const metadata = await extractVideoMetadata(videoPath);
104324
104472
  const framePattern = `frame_%05d.${format3}`;
104325
- const outputPattern = join7(videoOutputDir, framePattern);
104473
+ const outputPattern = join8(videoOutputDir, framePattern);
104326
104474
  const args = [
104327
104475
  "-ss",
104328
104476
  String(startTime),
@@ -104337,7 +104485,7 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
104337
104485
  ];
104338
104486
  if (format3 === "png") args.push("-compression_level", "6");
104339
104487
  args.push("-y", outputPattern);
104340
- return new Promise((resolve12, reject) => {
104488
+ return new Promise((resolve13, reject) => {
104341
104489
  const ffmpeg = spawn8("ffmpeg", args);
104342
104490
  let stderr = "";
104343
104491
  const onAbort = () => {
@@ -104370,9 +104518,9 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
104370
104518
  const framePaths = /* @__PURE__ */ new Map();
104371
104519
  const files = readdirSync4(videoOutputDir).filter((f) => f.startsWith("frame_") && f.endsWith(`.${format3}`)).sort();
104372
104520
  files.forEach((file, index) => {
104373
- framePaths.set(index, join7(videoOutputDir, file));
104521
+ framePaths.set(index, join8(videoOutputDir, file));
104374
104522
  });
104375
- resolve12({
104523
+ resolve13({
104376
104524
  videoId,
104377
104525
  srcPath: videoPath,
104378
104526
  outputDir: videoOutputDir,
@@ -104407,10 +104555,10 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2)
104407
104555
  try {
104408
104556
  let videoPath = video.src;
104409
104557
  if (!videoPath.startsWith("/") && !isHttpUrl(videoPath)) {
104410
- videoPath = join7(baseDir, videoPath);
104558
+ videoPath = join8(baseDir, videoPath);
104411
104559
  }
104412
104560
  if (isHttpUrl(videoPath)) {
104413
- const downloadDir = join7(options.outputDir, "_downloads");
104561
+ const downloadDir = join8(options.outputDir, "_downloads");
104414
104562
  mkdirSync5(downloadDir, { recursive: true });
104415
104563
  videoPath = await downloadToTemp(videoPath, downloadDir);
104416
104564
  }
@@ -104654,7 +104802,7 @@ function createVideoFrameInjector(frameLookup, config2) {
104654
104802
 
104655
104803
  // ../engine/src/services/audioMixer.ts
104656
104804
  import { existsSync as existsSync9, mkdirSync as mkdirSync6, rmSync as rmSync2 } from "fs";
104657
- import { join as join8, dirname as dirname6 } from "path";
104805
+ import { join as join9, dirname as dirname7 } from "path";
104658
104806
  function parseAudioElements(html) {
104659
104807
  const elements = [];
104660
104808
  const { document: document2 } = parseHTML(html);
@@ -104704,7 +104852,7 @@ function parseAudioElements(html) {
104704
104852
  }
104705
104853
  async function extractAudioFromVideo(videoPath, outputPath, options, signal, config2) {
104706
104854
  const ffmpegProcessTimeout = config2?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
104707
- const outputDir = dirname6(outputPath);
104855
+ const outputDir = dirname7(outputPath);
104708
104856
  if (!existsSync9(outputDir)) mkdirSync6(outputDir, { recursive: true });
104709
104857
  const args = ["-i", videoPath];
104710
104858
  if (options?.startTime !== void 0) args.push("-ss", String(options.startTime));
@@ -104731,7 +104879,7 @@ async function extractAudioFromVideo(videoPath, outputPath, options, signal, con
104731
104879
  }
104732
104880
  async function prepareAudioTrack(srcPath, outputPath, mediaStart, duration, signal, config2) {
104733
104881
  const ffmpegProcessTimeout = config2?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
104734
- const outputDir = dirname6(outputPath);
104882
+ const outputDir = dirname7(outputPath);
104735
104883
  if (!existsSync9(outputDir)) mkdirSync6(outputDir, { recursive: true });
104736
104884
  const args = [
104737
104885
  "-ss",
@@ -104767,7 +104915,7 @@ async function prepareAudioTrack(srcPath, outputPath, mediaStart, duration, sign
104767
104915
  }
104768
104916
  async function generateSilence(outputPath, duration, signal, config2) {
104769
104917
  const ffmpegProcessTimeout = config2?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
104770
- const outputDir = dirname6(outputPath);
104918
+ const outputDir = dirname7(outputPath);
104771
104919
  if (!existsSync9(outputDir)) mkdirSync6(outputDir, { recursive: true });
104772
104920
  const args = [
104773
104921
  "-f",
@@ -104810,7 +104958,7 @@ async function mixAudioTracks(tracks, outputPath, totalDuration, signal, config2
104810
104958
  error: result2.error
104811
104959
  };
104812
104960
  }
104813
- const outputDir = dirname6(outputPath);
104961
+ const outputDir = dirname7(outputPath);
104814
104962
  if (!existsSync9(outputDir)) mkdirSync6(outputDir, { recursive: true });
104815
104963
  const inputs = [];
104816
104964
  const filterParts = [];
@@ -104882,7 +105030,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
104882
105030
  try {
104883
105031
  let srcPath = element.src;
104884
105032
  if (!srcPath.startsWith("/") && !isHttpUrl(srcPath)) {
104885
- srcPath = join8(baseDir, srcPath);
105033
+ srcPath = join9(baseDir, srcPath);
104886
105034
  }
104887
105035
  if (isHttpUrl(srcPath)) {
104888
105036
  try {
@@ -104905,7 +105053,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
104905
105053
  }
104906
105054
  let audioSrcPath = srcPath;
104907
105055
  if (element.type === "video") {
104908
- const extractedPath = join8(workDir, `${element.id}-extracted.wav`);
105056
+ const extractedPath = join9(workDir, `${element.id}-extracted.wav`);
104909
105057
  const extractResult = await extractAudioFromVideo(
104910
105058
  srcPath,
104911
105059
  extractedPath,
@@ -104922,7 +105070,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
104922
105070
  }
104923
105071
  audioSrcPath = extractedPath;
104924
105072
  } else {
104925
- const trimmedPath = join8(workDir, `${element.id}-trimmed.wav`);
105073
+ const trimmedPath = join9(workDir, `${element.id}-trimmed.wav`);
104926
105074
  const prepResult = await prepareAudioTrack(
104927
105075
  srcPath,
104928
105076
  trimmedPath,
@@ -104967,7 +105115,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
104967
105115
  import { cpus, freemem, totalmem } from "os";
104968
105116
  import { existsSync as existsSync10, mkdirSync as mkdirSync7, readdirSync as readdirSync5 } from "fs";
104969
105117
  import { copyFile, rename as rename2 } from "fs/promises";
104970
- import { join as join9 } from "path";
105118
+ import { join as join10 } from "path";
104971
105119
  var MEMORY_PER_WORKER_MB = 256;
104972
105120
  var MIN_WORKERS = 1;
104973
105121
  var ABSOLUTE_MAX_WORKERS = 10;
@@ -105015,7 +105163,7 @@ function distributeFrames(totalFrames, workerCount, workDir) {
105015
105163
  workerId: i,
105016
105164
  startFrame,
105017
105165
  endFrame,
105018
- outputDir: join9(workDir, `worker-${i}`)
105166
+ outputDir: join10(workDir, `worker-${i}`)
105019
105167
  });
105020
105168
  }
105021
105169
  return tasks;
@@ -105122,8 +105270,8 @@ async function mergeWorkerFrames(workDir, tasks, outputDir) {
105122
105270
  }
105123
105271
  const files = readdirSync5(task.outputDir).filter((f) => f.startsWith("frame_") && (f.endsWith(".jpg") || f.endsWith(".png"))).sort();
105124
105272
  const copyTasks = files.map(async (file) => {
105125
- const sourcePath = join9(task.outputDir, file);
105126
- const targetPath = join9(outputDir, file);
105273
+ const sourcePath = join10(task.outputDir, file);
105274
+ const targetPath = join10(outputDir, file);
105127
105275
  try {
105128
105276
  await rename2(sourcePath, targetPath);
105129
105277
  } catch {
@@ -105137,33 +105285,33 @@ async function mergeWorkerFrames(workDir, tasks, outputDir) {
105137
105285
  }
105138
105286
 
105139
105287
  // src/services/renderOrchestrator.ts
105140
- import { join as join12, dirname as dirname9, resolve as resolve8 } from "path";
105288
+ import { join as join13, dirname as dirname10, resolve as resolve9 } from "path";
105141
105289
  import { randomUUID } from "crypto";
105142
105290
  import { freemem as freemem2 } from "os";
105143
105291
  import { fileURLToPath as fileURLToPath3 } from "url";
105144
105292
 
105145
105293
  // src/services/fileServer.ts
105146
105294
  import { readFileSync as readFileSync6, existsSync as existsSync12, statSync as statSync5 } from "node:fs";
105147
- import { join as join10, extname as extname3 } from "node:path";
105295
+ import { join as join11, extname as extname3 } from "node:path";
105148
105296
 
105149
105297
  // src/services/hyperframeRuntimeLoader.ts
105150
105298
  import { createHash as createHash2 } from "node:crypto";
105151
105299
  import { existsSync as existsSync11, readFileSync as readFileSync5 } from "node:fs";
105152
- import { dirname as dirname7, resolve as resolve6 } from "node:path";
105300
+ import { dirname as dirname8, resolve as resolve7 } from "node:path";
105153
105301
  import { fileURLToPath as fileURLToPath2 } from "node:url";
105154
- var PRODUCER_DIR = dirname7(fileURLToPath2(import.meta.url));
105155
- var SIBLING_MANIFEST_PATH = resolve6(PRODUCER_DIR, "hyperframe.manifest.json");
105156
- var MODULE_RELATIVE_MANIFEST_PATH = resolve6(
105302
+ var PRODUCER_DIR = dirname8(fileURLToPath2(import.meta.url));
105303
+ var SIBLING_MANIFEST_PATH = resolve7(PRODUCER_DIR, "hyperframe.manifest.json");
105304
+ var MODULE_RELATIVE_MANIFEST_PATH = resolve7(
105157
105305
  PRODUCER_DIR,
105158
105306
  "../../../core/dist/hyperframe.manifest.json"
105159
105307
  );
105160
105308
  var CWD_RELATIVE_MANIFEST_PATHS = [
105161
105309
  // When bundled to a single file (dist/public-server.js), the manifest
105162
105310
  // is copied as a sibling by build.mjs
105163
- resolve6(PRODUCER_DIR, "hyperframe.manifest.json"),
105164
- resolve6(process.cwd(), "packages/core/dist/hyperframe.manifest.json"),
105165
- resolve6(process.cwd(), "../core/dist/hyperframe.manifest.json"),
105166
- resolve6(process.cwd(), "core/dist/hyperframe.manifest.json")
105311
+ resolve7(PRODUCER_DIR, "hyperframe.manifest.json"),
105312
+ resolve7(process.cwd(), "packages/core/dist/hyperframe.manifest.json"),
105313
+ resolve7(process.cwd(), "../core/dist/hyperframe.manifest.json"),
105314
+ resolve7(process.cwd(), "core/dist/hyperframe.manifest.json")
105167
105315
  ];
105168
105316
  function resolveHyperframeManifestPath() {
105169
105317
  if (process.env.PRODUCER_HYPERFRAME_MANIFEST_PATH) {
@@ -105199,7 +105347,7 @@ function resolveVerifiedHyperframeRuntime() {
105199
105347
  `[HyperframeRuntimeLoader] Invalid manifest at ${manifestPath}; missing iife artifact or sha256.`
105200
105348
  );
105201
105349
  }
105202
- const runtimePath = resolve6(dirname7(manifestPath), runtimeFileName);
105350
+ const runtimePath = resolve7(dirname8(manifestPath), runtimeFileName);
105203
105351
  if (!existsSync11(runtimePath)) {
105204
105352
  throw new Error(`[HyperframeRuntimeLoader] Missing runtime artifact at ${runtimePath}.`);
105205
105353
  }
@@ -105450,11 +105598,11 @@ function createFileServer2(options) {
105450
105598
  let requestPath = c.req.path;
105451
105599
  if (requestPath === "/") requestPath = "/index.html";
105452
105600
  const relativePath = requestPath.replace(/^\//, "");
105453
- const compiledPath = compiledDir ? join10(compiledDir, relativePath) : null;
105601
+ const compiledPath = compiledDir ? join11(compiledDir, relativePath) : null;
105454
105602
  const hasCompiledFile = Boolean(
105455
105603
  compiledPath && existsSync12(compiledPath) && statSync5(compiledPath).isFile()
105456
105604
  );
105457
- const filePath = hasCompiledFile ? compiledPath : join10(projectDir, relativePath);
105605
+ const filePath = hasCompiledFile ? compiledPath : join11(projectDir, relativePath);
105458
105606
  if (!existsSync12(filePath) || !statSync5(filePath).isFile()) {
105459
105607
  return c.text("Not found", 404);
105460
105608
  }
@@ -105472,22 +105620,29 @@ function createFileServer2(options) {
105472
105620
  headers: { "Content-Type": contentType }
105473
105621
  });
105474
105622
  });
105475
- return new Promise((resolve12) => {
105623
+ return new Promise((resolve13) => {
105624
+ const connections = /* @__PURE__ */ new Set();
105476
105625
  const server = serve({ fetch: app.fetch, port }, (info) => {
105477
- const actualPort = info.port;
105478
- const url = `http://localhost:${actualPort}`;
105479
- resolve12({
105480
- url,
105481
- port: actualPort,
105482
- close: () => server.close()
105626
+ resolve13({
105627
+ url: `http://localhost:${info.port}`,
105628
+ port: info.port,
105629
+ close: () => {
105630
+ for (const socket of connections) socket.destroy();
105631
+ connections.clear();
105632
+ server.close();
105633
+ }
105483
105634
  });
105484
105635
  });
105636
+ server.on("connection", (socket) => {
105637
+ connections.add(socket);
105638
+ socket.on("close", () => connections.delete(socket));
105639
+ });
105485
105640
  });
105486
105641
  }
105487
105642
 
105488
105643
  // src/services/htmlCompiler.ts
105489
105644
  import { readFileSync as readFileSync7, existsSync as existsSync13, mkdirSync as mkdirSync8 } from "fs";
105490
- import { join as join11, dirname as dirname8, resolve as resolve7 } from "path";
105645
+ import { join as join12, dirname as dirname9, resolve as resolve8 } from "path";
105491
105646
 
105492
105647
  // src/services/fontData.generated.ts
105493
105648
  var EMBEDDED_FONT_DATA = /* @__PURE__ */ new Map([
@@ -105740,7 +105895,7 @@ async function resolveMediaDuration(src, mediaStart, baseDir, downloadDir, tagNa
105740
105895
  return { duration: 0, resolvedPath: src };
105741
105896
  }
105742
105897
  } else if (!filePath.startsWith("/")) {
105743
- filePath = join11(baseDir, filePath);
105898
+ filePath = join12(baseDir, filePath);
105744
105899
  }
105745
105900
  if (!existsSync13(filePath)) {
105746
105901
  return { duration: 0, resolvedPath: filePath };
@@ -105806,7 +105961,7 @@ async function parseSubCompositions(html, projectDir, downloadDir, parentOffset
105806
105961
  const elEnd = elEndRaw ? parseFloat(elEndRaw) : Infinity;
105807
105962
  const absoluteStart = parentOffset + elStart;
105808
105963
  const absoluteEnd = Math.min(parentEnd, isFinite(elEnd) ? parentOffset + elEnd : Infinity);
105809
- const filePath = resolve7(projectDir, srcPath);
105964
+ const filePath = resolve8(projectDir, srcPath);
105810
105965
  if (visited.has(filePath)) {
105811
105966
  continue;
105812
105967
  }
@@ -105822,7 +105977,7 @@ async function parseSubCompositions(html, projectDir, downloadDir, parentOffset
105822
105977
  workItems.map(async (item) => {
105823
105978
  const { html: compiledSub } = await compileHtmlFile(
105824
105979
  item.rawSubHtml,
105825
- dirname8(item.filePath),
105980
+ dirname9(item.filePath),
105826
105981
  downloadDir
105827
105982
  );
105828
105983
  const nested = await parseSubCompositions(
@@ -106001,12 +106156,13 @@ function inlineSubCompositions(html, subCompositions, projectDir) {
106001
106156
  if (!hosts.length) return html;
106002
106157
  const collectedStyles = [];
106003
106158
  const collectedScripts = [];
106159
+ const collectedExternalScriptSrcs = [];
106004
106160
  for (const host of hosts) {
106005
106161
  const srcPath = host.getAttribute("data-composition-src");
106006
106162
  if (!srcPath) continue;
106007
106163
  let compHtml = subCompositions.get(srcPath) || null;
106008
106164
  if (!compHtml) {
106009
- const filePath = resolve7(projectDir, srcPath);
106165
+ const filePath = resolve8(projectDir, srcPath);
106010
106166
  if (existsSync13(filePath)) {
106011
106167
  compHtml = readFileSync7(filePath, "utf-8");
106012
106168
  }
@@ -106034,7 +106190,13 @@ function inlineSubCompositions(html, subCompositions, projectDir) {
106034
106190
  }
106035
106191
  for (const scriptEl of contentDoc.querySelectorAll("script")) {
106036
106192
  const src = (scriptEl.getAttribute("src") || "").trim();
106037
- if (src) continue;
106193
+ if (src) {
106194
+ if (!collectedExternalScriptSrcs.includes(src)) {
106195
+ collectedExternalScriptSrcs.push(src);
106196
+ }
106197
+ scriptEl.remove();
106198
+ continue;
106199
+ }
106038
106200
  const content = (scriptEl.textContent || "").trim();
106039
106201
  if (content) {
106040
106202
  const scriptMountCompId = compId || inferredCompId || "";
@@ -106061,6 +106223,13 @@ function inlineSubCompositions(html, subCompositions, projectDir) {
106061
106223
  }
106062
106224
  scriptEl.remove();
106063
106225
  }
106226
+ const rewriteTarget = innerRoot || contentDoc;
106227
+ rewriteAssetPaths(
106228
+ rewriteTarget.querySelectorAll("[src], [href]"),
106229
+ srcPath,
106230
+ (el, attr) => (el.getAttribute(attr) || "").trim(),
106231
+ (el, attr, val) => el.setAttribute(attr, val)
106232
+ );
106064
106233
  if (innerRoot) {
106065
106234
  const innerW = innerRoot.getAttribute("data-width");
106066
106235
  const innerH = innerRoot.getAttribute("data-height");
@@ -106104,6 +106273,21 @@ function inlineSubCompositions(html, subCompositions, projectDir) {
106104
106273
  styleEl.textContent = collectedStyles.join("\n\n");
106105
106274
  head.appendChild(styleEl);
106106
106275
  }
106276
+ if (collectedExternalScriptSrcs.length && body) {
106277
+ const existingScriptSrcs = new Set(
106278
+ Array.from(document2.querySelectorAll("script[src]")).map(
106279
+ (el) => (el.getAttribute("src") || "").trim()
106280
+ )
106281
+ );
106282
+ for (const src of collectedExternalScriptSrcs) {
106283
+ if (!existingScriptSrcs.has(src)) {
106284
+ const scriptEl = document2.createElement("script");
106285
+ scriptEl.setAttribute("src", src);
106286
+ body.appendChild(scriptEl);
106287
+ existingScriptSrcs.add(src);
106288
+ }
106289
+ }
106290
+ }
106107
106291
  if (collectedScripts.length && body) {
106108
106292
  const scriptEl = document2.createElement("script");
106109
106293
  scriptEl.textContent = collectedScripts.join("\n;\n");
@@ -106154,7 +106338,7 @@ async function compileForRender(projectDir, htmlPath, downloadDir) {
106154
106338
  const audios = dedupeElementsById([...subAudios, ...mainAudios]);
106155
106339
  for (const video of videos) {
106156
106340
  if (isHttpUrl(video.src)) continue;
106157
- const videoPath = resolve7(projectDir, video.src);
106341
+ const videoPath = resolve8(projectDir, video.src);
106158
106342
  const reencode = `ffmpeg -i "${video.src}" -c:v libx264 -r 30 -g 30 -keyint_min 30 -movflags +faststart -c:a copy output.mp4`;
106159
106343
  Promise.all([analyzeKeyframeIntervals(videoPath), extractVideoMetadata(videoPath)]).then(([analysis, metadata]) => {
106160
106344
  if (analysis.isProblematic) {
@@ -106396,12 +106580,12 @@ function installDebugLogger(logPath, log = defaultLogger) {
106396
106580
  };
106397
106581
  }
106398
106582
  function writeCompiledArtifacts(compiled, workDir, includeSummary) {
106399
- const compileDir = join12(workDir, "compiled");
106583
+ const compileDir = join13(workDir, "compiled");
106400
106584
  mkdirSync9(compileDir, { recursive: true });
106401
- writeFileSync3(join12(compileDir, "index.html"), compiled.html, "utf-8");
106585
+ writeFileSync3(join13(compileDir, "index.html"), compiled.html, "utf-8");
106402
106586
  for (const [srcPath, html] of compiled.subCompositions) {
106403
- const outPath = join12(compileDir, srcPath);
106404
- mkdirSync9(dirname9(outPath), { recursive: true });
106587
+ const outPath = join13(compileDir, srcPath);
106588
+ mkdirSync9(dirname10(outPath), { recursive: true });
106405
106589
  writeFileSync3(outPath, html, "utf-8");
106406
106590
  }
106407
106591
  if (includeSummary) {
@@ -106425,7 +106609,7 @@ function writeCompiledArtifacts(compiled, workDir, includeSummary) {
106425
106609
  })),
106426
106610
  subCompositions: Array.from(compiled.subCompositions.keys())
106427
106611
  };
106428
- writeFileSync3(join12(compileDir, "summary.json"), JSON.stringify(summary, null, 2), "utf-8");
106612
+ writeFileSync3(join13(compileDir, "summary.json"), JSON.stringify(summary, null, 2), "utf-8");
106429
106613
  }
106430
106614
  }
106431
106615
  function createRenderJob(config2) {
@@ -106468,10 +106652,10 @@ function extractStandaloneEntryFromIndex(indexHtml, entryFile) {
106468
106652
  return document2.toString();
106469
106653
  }
106470
106654
  async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSignal) {
106471
- const moduleDir = dirname9(fileURLToPath3(import.meta.url));
106472
- const producerRoot = process.env.PRODUCER_RENDERS_DIR ? resolve8(process.env.PRODUCER_RENDERS_DIR, "..") : resolve8(moduleDir, "../..");
106473
- const debugDir = join12(producerRoot, ".debug");
106474
- const workDir = job.config.debug ? join12(debugDir, job.id) : join12(dirname9(outputPath), `work-${job.id}`);
106655
+ const moduleDir = dirname10(fileURLToPath3(import.meta.url));
106656
+ const producerRoot = process.env.PRODUCER_RENDERS_DIR ? resolve9(process.env.PRODUCER_RENDERS_DIR, "..") : resolve9(moduleDir, "../..");
106657
+ const debugDir = join13(producerRoot, ".debug");
106658
+ const workDir = job.config.debug ? join13(debugDir, job.id) : join13(dirname10(outputPath), `work-${job.id}`);
106475
106659
  const pipelineStart = Date.now();
106476
106660
  const log = job.config.logger ?? defaultLogger;
106477
106661
  let fileServer = null;
@@ -106479,7 +106663,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
106479
106663
  let lastBrowserConsole = [];
106480
106664
  let restoreLogger = null;
106481
106665
  const perfStages = {};
106482
- const perfOutputPath = join12(workDir, "perf-summary.json");
106666
+ const perfOutputPath = join13(workDir, "perf-summary.json");
106483
106667
  const cfg = { ...job.config.producerConfig ?? resolveConfig() };
106484
106668
  const outputFormat = job.config.format ?? "mp4";
106485
106669
  const isWebm = outputFormat === "webm";
@@ -106499,19 +106683,19 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
106499
106683
  assertNotAborted();
106500
106684
  if (!existsSync14(workDir)) mkdirSync9(workDir, { recursive: true });
106501
106685
  if (job.config.debug) {
106502
- const logPath = join12(workDir, "render.log");
106686
+ const logPath = join13(workDir, "render.log");
106503
106687
  restoreLogger = installDebugLogger(logPath, log);
106504
106688
  }
106505
106689
  const entryFile = job.config.entryFile || "index.html";
106506
- let htmlPath = join12(projectDir, entryFile);
106690
+ let htmlPath = join13(projectDir, entryFile);
106507
106691
  if (!existsSync14(htmlPath)) {
106508
106692
  throw new Error(`Entry file not found: ${htmlPath}`);
106509
106693
  }
106510
106694
  assertNotAborted();
106511
106695
  const rawEntry = readFileSync8(htmlPath, "utf-8");
106512
106696
  if (entryFile !== "index.html" && rawEntry.trimStart().startsWith("<template")) {
106513
- const wrapperPath = join12(workDir, "standalone-entry.html");
106514
- const projectIndexPath = join12(projectDir, "index.html");
106697
+ const wrapperPath = join13(workDir, "standalone-entry.html");
106698
+ const projectIndexPath = join13(projectDir, "index.html");
106515
106699
  if (!existsSync14(projectIndexPath)) {
106516
106700
  throw new Error(
106517
106701
  `Template entry file "${entryFile}" requires a project index.html to extract its render shell.`
@@ -106535,7 +106719,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
106535
106719
  const stage1Start = Date.now();
106536
106720
  updateJobStatus(job, "preprocessing", "Compiling composition", 5, onProgress);
106537
106721
  const compileStart = Date.now();
106538
- let compiled = await compileForRender(projectDir, htmlPath, join12(workDir, "downloads"));
106722
+ let compiled = await compileForRender(projectDir, htmlPath, join13(workDir, "downloads"));
106539
106723
  assertNotAborted();
106540
106724
  perfStages.compileOnlyMs = Date.now() - compileStart;
106541
106725
  writeCompiledArtifacts(compiled, workDir, Boolean(job.config.debug));
@@ -106564,7 +106748,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
106564
106748
  reasons.push(`${compiled.unresolvedCompositions.length} unresolved composition(s)`);
106565
106749
  fileServer = await createFileServer2({
106566
106750
  projectDir,
106567
- compiledDir: join12(workDir, "compiled"),
106751
+ compiledDir: join13(workDir, "compiled"),
106568
106752
  port: 0
106569
106753
  });
106570
106754
  assertNotAborted();
@@ -106577,7 +106761,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
106577
106761
  };
106578
106762
  probeSession = await createCaptureSession(
106579
106763
  fileServer.url,
106580
- join12(workDir, "probe"),
106764
+ join13(workDir, "probe"),
106581
106765
  captureOpts,
106582
106766
  null,
106583
106767
  cfg
@@ -106609,7 +106793,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
106609
106793
  compiled,
106610
106794
  resolutions,
106611
106795
  projectDir,
106612
- join12(workDir, "downloads")
106796
+ join13(workDir, "downloads")
106613
106797
  );
106614
106798
  assertNotAborted();
106615
106799
  composition.videos = compiled.videos;
@@ -106706,7 +106890,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
106706
106890
  const extractionResult = await extractAllVideoFrames(
106707
106891
  composition.videos,
106708
106892
  projectDir,
106709
- { fps: job.config.fps, outputDir: join12(workDir, "video-frames") },
106893
+ { fps: job.config.fps, outputDir: join13(workDir, "video-frames") },
106710
106894
  abortSignal
106711
106895
  );
106712
106896
  assertNotAborted();
@@ -106738,13 +106922,13 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
106738
106922
  }
106739
106923
  const stage3Start = Date.now();
106740
106924
  updateJobStatus(job, "preprocessing", "Processing audio tracks", 20, onProgress);
106741
- const audioOutputPath = join12(workDir, "audio.aac");
106925
+ const audioOutputPath = join13(workDir, "audio.aac");
106742
106926
  let hasAudio = false;
106743
106927
  if (composition.audios.length > 0) {
106744
106928
  const audioResult = await processCompositionAudio(
106745
106929
  composition.audios,
106746
106930
  projectDir,
106747
- join12(workDir, "audio-work"),
106931
+ join13(workDir, "audio-work"),
106748
106932
  audioOutputPath,
106749
106933
  job.duration,
106750
106934
  abortSignal
@@ -106760,12 +106944,12 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
106760
106944
  if (!fileServer) {
106761
106945
  fileServer = await createFileServer2({
106762
106946
  projectDir,
106763
- compiledDir: join12(workDir, "compiled"),
106947
+ compiledDir: join13(workDir, "compiled"),
106764
106948
  port: 0
106765
106949
  });
106766
106950
  assertNotAborted();
106767
106951
  }
106768
- const framesDir = join12(workDir, "captured-frames");
106952
+ const framesDir = join13(workDir, "captured-frames");
106769
106953
  if (!existsSync14(framesDir)) mkdirSync9(framesDir, { recursive: true });
106770
106954
  const captureOptions = {
106771
106955
  width,
@@ -106776,7 +106960,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
106776
106960
  };
106777
106961
  const workerCount = calculateOptimalWorkers(job.totalFrames, job.config.workers, cfg);
106778
106962
  const videoExt = isWebm ? ".webm" : ".mp4";
106779
- const videoOnlyPath = join12(workDir, `video-only${videoExt}`);
106963
+ const videoOnlyPath = join13(workDir, `video-only${videoExt}`);
106780
106964
  const preset = getEncoderPreset(job.config.quality, outputFormat);
106781
106965
  job.framesRendered = 0;
106782
106966
  let streamingEncoder = null;
@@ -107055,7 +107239,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
107055
107239
  }
107056
107240
  if (job.config.debug) {
107057
107241
  if (existsSync14(outputPath)) {
107058
- const debugOutput = join12(workDir, isWebm ? "output.webm" : "output.mp4");
107242
+ const debugOutput = join13(workDir, isWebm ? "output.webm" : "output.mp4");
107059
107243
  copyFileSync2(outputPath, debugOutput);
107060
107244
  }
107061
107245
  } else {
@@ -107150,7 +107334,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
107150
107334
 
107151
107335
  // src/services/hyperframeLint.ts
107152
107336
  import { existsSync as existsSync15, readFileSync as readFileSync9, statSync as statSync6 } from "node:fs";
107153
- import { resolve as resolve9, join as join13 } from "node:path";
107337
+ import { resolve as resolve10, join as join14 } from "node:path";
107154
107338
  function isStringRecord(value) {
107155
107339
  if (!value || typeof value !== "object" || Array.isArray(value)) {
107156
107340
  return false;
@@ -107177,7 +107361,7 @@ function pickEntryFile(files, preferredEntryFile) {
107177
107361
  return null;
107178
107362
  }
107179
107363
  function readProjectEntryFile(projectDir, preferredEntryFile) {
107180
- const absProjectDir = resolve9(projectDir);
107364
+ const absProjectDir = resolve10(projectDir);
107181
107365
  if (!existsSync15(absProjectDir) || !statSync6(absProjectDir).isDirectory()) {
107182
107366
  return { error: `Project directory not found: ${absProjectDir}` };
107183
107367
  }
@@ -107185,7 +107369,7 @@ function readProjectEntryFile(projectDir, preferredEntryFile) {
107185
107369
  (value) => typeof value === "string" && value.trim().length > 0
107186
107370
  );
107187
107371
  for (const entryFile of entryCandidates) {
107188
- const absoluteEntryPath = resolve9(absProjectDir, entryFile);
107372
+ const absoluteEntryPath = resolve10(absProjectDir, entryFile);
107189
107373
  if (!absoluteEntryPath.startsWith(absProjectDir)) {
107190
107374
  return { error: `Entry file must stay inside project directory: ${entryFile}` };
107191
107375
  }
@@ -107198,7 +107382,7 @@ function readProjectEntryFile(projectDir, preferredEntryFile) {
107198
107382
  }
107199
107383
  }
107200
107384
  return {
107201
- error: `No HTML entry file found in project directory: ${join13(absProjectDir, preferredEntryFile || "index.html")}`
107385
+ error: `No HTML entry file found in project directory: ${join14(absProjectDir, preferredEntryFile || "index.html")}`
107202
107386
  };
107203
107387
  }
107204
107388
  function prepareHyperframeLintBody(body) {
@@ -107239,13 +107423,13 @@ function runHyperframeLint(prepared) {
107239
107423
  }
107240
107424
 
107241
107425
  // src/utils/paths.ts
107242
- import { resolve as resolve10, basename as basename2, join as join14 } from "node:path";
107243
- var DEFAULT_RENDERS_DIR = process.env.PRODUCER_RENDERS_DIR ?? resolve10(new URL(import.meta.url).pathname, "../../..", "renders");
107426
+ import { resolve as resolve11, basename as basename2, join as join15 } from "node:path";
107427
+ var DEFAULT_RENDERS_DIR = process.env.PRODUCER_RENDERS_DIR ?? resolve11(new URL(import.meta.url).pathname, "../../..", "renders");
107244
107428
  function resolveRenderPaths(projectDir, outputPath, rendersDir = DEFAULT_RENDERS_DIR) {
107245
- const absoluteProjectDir = resolve10(projectDir);
107429
+ const absoluteProjectDir = resolve11(projectDir);
107246
107430
  const projectName = basename2(absoluteProjectDir);
107247
- const resolvedOutputPath = outputPath ?? join14(rendersDir, `${projectName}.mp4`);
107248
- const absoluteOutputPath = resolve10(resolvedOutputPath);
107431
+ const resolvedOutputPath = outputPath ?? join15(rendersDir, `${projectName}.mp4`);
107432
+ const absoluteOutputPath = resolve11(resolvedOutputPath);
107249
107433
  return { absoluteProjectDir, absoluteOutputPath };
107250
107434
  }
107251
107435
 
@@ -107265,12 +107449,12 @@ async function prepareRenderBody(body) {
107265
107449
  const options = parseRenderOptions(body);
107266
107450
  const projectDir = typeof body.projectDir === "string" ? body.projectDir : void 0;
107267
107451
  if (projectDir) {
107268
- const absProjectDir = resolve11(projectDir);
107452
+ const absProjectDir = resolve12(projectDir);
107269
107453
  if (!existsSync16(absProjectDir) || !statSync7(absProjectDir).isDirectory()) {
107270
107454
  return { error: `Project directory not found: ${absProjectDir}` };
107271
107455
  }
107272
107456
  const entry = options.entryFile || "index.html";
107273
- if (!existsSync16(resolve11(absProjectDir, entry))) {
107457
+ if (!existsSync16(resolve12(absProjectDir, entry))) {
107274
107458
  return { error: `Entry file "${entry}" not found in project directory: ${absProjectDir}` };
107275
107459
  }
107276
107460
  return { prepared: { input: { projectDir: absProjectDir, ...options } } };
@@ -107295,8 +107479,8 @@ async function prepareRenderBody(body) {
107295
107479
  }
107296
107480
  }
107297
107481
  const tempRoot = process.env.PRODUCER_TMP_PROJECT_DIR || tmpdir2();
107298
- const tempProjectDir = mkdtempSync(join15(tempRoot, "producer-project-"));
107299
- writeFileSync4(join15(tempProjectDir, "index.html"), htmlContent, "utf-8");
107482
+ const tempProjectDir = mkdtempSync(join16(tempRoot, "producer-project-"));
107483
+ writeFileSync4(join16(tempProjectDir, "index.html"), htmlContent, "utf-8");
107300
107484
  return {
107301
107485
  prepared: {
107302
107486
  input: {
@@ -107311,7 +107495,7 @@ function resolveOutputPath(projectDir, outputCandidate, rendersDir, log) {
107311
107495
  try {
107312
107496
  return resolveRenderPaths(projectDir, outputCandidate, rendersDir).absoluteOutputPath;
107313
107497
  } catch (error) {
107314
- const fallbackPath = resolve11(rendersDir, `producer-fallback-${Date.now()}.mp4`);
107498
+ const fallbackPath = resolve12(rendersDir, `producer-fallback-${Date.now()}.mp4`);
107315
107499
  log.warn("Failed to resolve output path, using fallback", {
107316
107500
  fallback: fallbackPath,
107317
107501
  error: error instanceof Error ? error.message : String(error)
@@ -107416,7 +107600,7 @@ function createRenderHandlers(options = {}) {
107416
107600
  rendersDir,
107417
107601
  log
107418
107602
  );
107419
- const outputDir = dirname10(absoluteOutputPath);
107603
+ const outputDir = dirname11(absoluteOutputPath);
107420
107604
  if (!existsSync16(outputDir)) mkdirSync10(outputDir, { recursive: true });
107421
107605
  log.info("render started", {
107422
107606
  requestId,
@@ -107525,7 +107709,7 @@ function createRenderHandlers(options = {}) {
107525
107709
  rendersDir,
107526
107710
  log
107527
107711
  );
107528
- const outputDir = dirname10(absoluteOutputPath);
107712
+ const outputDir = dirname11(absoluteOutputPath);
107529
107713
  if (!existsSync16(outputDir)) mkdirSync10(outputDir, { recursive: true });
107530
107714
  log.info("render-stream started", { requestId, projectDir: input2.projectDir });
107531
107715
  const job = createRenderJob({
@@ -107669,7 +107853,7 @@ function startServer(options = {}) {
107669
107853
  process.on("SIGINT", () => shutdown("SIGINT"));
107670
107854
  return server;
107671
107855
  }
107672
- var entryScript = process.argv[1] ? resolve11(process.argv[1]) : "";
107856
+ var entryScript = process.argv[1] ? resolve12(process.argv[1]) : "";
107673
107857
  var isPublicServerEntry = entryScript.endsWith("/public-server.js") || entryScript.endsWith("/src/server.ts");
107674
107858
  if (isPublicServerEntry) {
107675
107859
  const { values } = parseArgs({