@hyperframes/producer 0.1.15 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2148,11 +2148,11 @@ function __extends(d, b) {
2148
2148
  }
2149
2149
  function __awaiter(thisArg, _arguments, P, generator) {
2150
2150
  function adopt(value) {
2151
- return value instanceof P ? value : new P(function(resolve12) {
2152
- resolve12(value);
2151
+ return value instanceof P ? value : new P(function(resolve13) {
2152
+ resolve13(value);
2153
2153
  });
2154
2154
  }
2155
- return new (P || (P = Promise))(function(resolve12, reject) {
2155
+ return new (P || (P = Promise))(function(resolve13, reject) {
2156
2156
  function fulfilled(value) {
2157
2157
  try {
2158
2158
  step(generator.next(value));
@@ -2168,7 +2168,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
2168
2168
  }
2169
2169
  }
2170
2170
  function step(result) {
2171
- result.done ? resolve12(result.value) : adopt(result.value).then(fulfilled, rejected);
2171
+ result.done ? resolve13(result.value) : adopt(result.value).then(fulfilled, rejected);
2172
2172
  }
2173
2173
  step((generator = generator.apply(thisArg, _arguments || [])).next());
2174
2174
  });
@@ -2331,14 +2331,14 @@ function __asyncValues(o) {
2331
2331
  }, i);
2332
2332
  function verb(n) {
2333
2333
  i[n] = o[n] && function(v) {
2334
- return new Promise(function(resolve12, reject) {
2335
- v = o[n](v), settle(resolve12, reject, v.done, v.value);
2334
+ return new Promise(function(resolve13, reject) {
2335
+ v = o[n](v), settle(resolve13, reject, v.done, v.value);
2336
2336
  });
2337
2337
  };
2338
2338
  }
2339
- function settle(resolve12, reject, d, v) {
2339
+ function settle(resolve13, reject, d, v) {
2340
2340
  Promise.resolve(v).then(function(v2) {
2341
- resolve12({ value: v2, done: d });
2341
+ resolve13({ value: v2, done: d });
2342
2342
  }, reject);
2343
2343
  }
2344
2344
  }
@@ -2863,7 +2863,7 @@ function of() {
2863
2863
  }
2864
2864
  function lastValueFrom(source2, config2) {
2865
2865
  var hasConfig = typeof config2 === "object";
2866
- return new Promise(function(resolve12, reject) {
2866
+ return new Promise(function(resolve13, reject) {
2867
2867
  var _hasValue = false;
2868
2868
  var _value;
2869
2869
  source2.subscribe({
@@ -2874,9 +2874,9 @@ function lastValueFrom(source2, config2) {
2874
2874
  error: reject,
2875
2875
  complete: function() {
2876
2876
  if (_hasValue) {
2877
- resolve12(_value);
2877
+ resolve13(_value);
2878
2878
  } else if (hasConfig) {
2879
- resolve12(config2.defaultValue);
2879
+ resolve13(config2.defaultValue);
2880
2880
  } else {
2881
2881
  reject(new EmptyError());
2882
2882
  }
@@ -2886,16 +2886,16 @@ function lastValueFrom(source2, config2) {
2886
2886
  }
2887
2887
  function firstValueFrom(source2, config2) {
2888
2888
  var hasConfig = typeof config2 === "object";
2889
- return new Promise(function(resolve12, reject) {
2889
+ return new Promise(function(resolve13, reject) {
2890
2890
  var subscriber = new SafeSubscriber({
2891
2891
  next: function(value) {
2892
- resolve12(value);
2892
+ resolve13(value);
2893
2893
  subscriber.unsubscribe();
2894
2894
  },
2895
2895
  error: reject,
2896
2896
  complete: function() {
2897
2897
  if (hasConfig) {
2898
- resolve12(config2.defaultValue);
2898
+ resolve13(config2.defaultValue);
2899
2899
  } else {
2900
2900
  reject(new EmptyError());
2901
2901
  }
@@ -3934,7 +3934,7 @@ var init_rxjs = __esm({
3934
3934
  Observable2.prototype.forEach = function(next, promiseCtor) {
3935
3935
  var _this = this;
3936
3936
  promiseCtor = getPromiseCtor(promiseCtor);
3937
- return new promiseCtor(function(resolve12, reject) {
3937
+ return new promiseCtor(function(resolve13, reject) {
3938
3938
  var subscriber = new SafeSubscriber({
3939
3939
  next: function(value) {
3940
3940
  try {
@@ -3945,7 +3945,7 @@ var init_rxjs = __esm({
3945
3945
  }
3946
3946
  },
3947
3947
  error: reject,
3948
- complete: resolve12
3948
+ complete: resolve13
3949
3949
  });
3950
3950
  _this.subscribe(subscriber);
3951
3951
  });
@@ -3967,14 +3967,14 @@ var init_rxjs = __esm({
3967
3967
  Observable2.prototype.toPromise = function(promiseCtor) {
3968
3968
  var _this = this;
3969
3969
  promiseCtor = getPromiseCtor(promiseCtor);
3970
- return new promiseCtor(function(resolve12, reject) {
3970
+ return new promiseCtor(function(resolve13, reject) {
3971
3971
  var value;
3972
3972
  _this.subscribe(function(x) {
3973
3973
  return value = x;
3974
3974
  }, function(err) {
3975
3975
  return reject(err);
3976
3976
  }, function() {
3977
- return resolve12(value);
3977
+ return resolve13(value);
3978
3978
  });
3979
3979
  });
3980
3980
  };
@@ -6404,8 +6404,8 @@ var init_Deferred = __esm({
6404
6404
  // SAFETY: This is ensured by #taskPromise.
6405
6405
  #resolve;
6406
6406
  // TODO: Switch to Promise.withResolvers with Node 22
6407
- #taskPromise = new Promise((resolve12) => {
6408
- this.#resolve = resolve12;
6407
+ #taskPromise = new Promise((resolve13) => {
6408
+ this.#resolve = resolve13;
6409
6409
  });
6410
6410
  #timeoutId;
6411
6411
  #timeoutError;
@@ -6495,12 +6495,12 @@ var init_Mutex = __esm({
6495
6495
  return new _Mutex.Guard(this, onRelease);
6496
6496
  }
6497
6497
  release() {
6498
- const resolve12 = this.#acquirers.shift();
6499
- if (!resolve12) {
6498
+ const resolve13 = this.#acquirers.shift();
6499
+ if (!resolve13) {
6500
6500
  this.#locked = false;
6501
6501
  return;
6502
6502
  }
6503
- resolve12();
6503
+ resolve13();
6504
6504
  }
6505
6505
  };
6506
6506
  }
@@ -8515,12 +8515,12 @@ var init_locators = __esm({
8515
8515
  }
8516
8516
  return defer(() => {
8517
8517
  return from(handle.evaluate((element) => {
8518
- return new Promise((resolve12) => {
8518
+ return new Promise((resolve13) => {
8519
8519
  window.requestAnimationFrame(() => {
8520
8520
  const rect1 = element.getBoundingClientRect();
8521
8521
  window.requestAnimationFrame(() => {
8522
8522
  const rect2 = element.getBoundingClientRect();
8523
- resolve12([
8523
+ resolve13([
8524
8524
  {
8525
8525
  x: rect1.x,
8526
8526
  y: rect1.y,
@@ -10259,9 +10259,9 @@ var init_ElementHandle = __esm({
10259
10259
  const handle = await this.#asSVGElementHandle();
10260
10260
  const target = __addDisposableResource6(env_5, handle && await handle.#getOwnerSVGElement(), false);
10261
10261
  return await (target ?? this).evaluate(async (element, threshold) => {
10262
- const visibleRatio = await new Promise((resolve12) => {
10262
+ const visibleRatio = await new Promise((resolve13) => {
10263
10263
  const observer = new IntersectionObserver((entries2) => {
10264
- resolve12(entries2[0].intersectionRatio);
10264
+ resolve13(entries2[0].intersectionRatio);
10265
10265
  observer.disconnect();
10266
10266
  });
10267
10267
  observer.observe(element);
@@ -10907,7 +10907,7 @@ var init_Frame = __esm({
10907
10907
  }
10908
10908
  type = type ?? "text/javascript";
10909
10909
  return await this.mainRealm().transferHandle(await this.isolatedRealm().evaluateHandle(async ({ url, id, type: type2, content: content2 }) => {
10910
- return await new Promise((resolve12, reject) => {
10910
+ return await new Promise((resolve13, reject) => {
10911
10911
  const script = document.createElement("script");
10912
10912
  script.type = type2;
10913
10913
  script.text = content2;
@@ -10920,12 +10920,12 @@ var init_Frame = __esm({
10920
10920
  if (url) {
10921
10921
  script.src = url;
10922
10922
  script.addEventListener("load", () => {
10923
- resolve12(script);
10923
+ resolve13(script);
10924
10924
  }, { once: true });
10925
10925
  document.head.appendChild(script);
10926
10926
  } else {
10927
10927
  document.head.appendChild(script);
10928
- resolve12(script);
10928
+ resolve13(script);
10929
10929
  }
10930
10930
  });
10931
10931
  }, { ...options, type, content }));
@@ -10945,7 +10945,7 @@ var init_Frame = __esm({
10945
10945
  options.content = content;
10946
10946
  }
10947
10947
  return await this.mainRealm().transferHandle(await this.isolatedRealm().evaluateHandle(async ({ url, content: content2 }) => {
10948
- return await new Promise((resolve12, reject) => {
10948
+ return await new Promise((resolve13, reject) => {
10949
10949
  let element;
10950
10950
  if (!url) {
10951
10951
  element = document.createElement("style");
@@ -10957,7 +10957,7 @@ var init_Frame = __esm({
10957
10957
  element = link;
10958
10958
  }
10959
10959
  element.addEventListener("load", () => {
10960
- resolve12(element);
10960
+ resolve13(element);
10961
10961
  }, { once: true });
10962
10962
  element.addEventListener("error", (event) => {
10963
10963
  reject(new Error(event.message ?? "Could not load style"));
@@ -12696,9 +12696,9 @@ var init_Page = __esm({
12696
12696
  ++this.#screencastSessionCount;
12697
12697
  if (!this.#startScreencastPromise) {
12698
12698
  this.#startScreencastPromise = this.mainFrame().client.send("Page.startScreencast", { format: "png" }).then(() => {
12699
- return new Promise((resolve12) => {
12699
+ return new Promise((resolve13) => {
12700
12700
  return this.mainFrame().client.once("Page.screencastFrame", () => {
12701
- return resolve12();
12701
+ return resolve13();
12702
12702
  });
12703
12703
  });
12704
12704
  });
@@ -16016,11 +16016,11 @@ function addPageBinding(type, name, prefix) {
16016
16016
  return value instanceof Node;
16017
16017
  })
16018
16018
  }));
16019
- return new Promise((resolve12, reject) => {
16019
+ return new Promise((resolve13, reject) => {
16020
16020
  callPuppeteer.callbacks.set(seq, {
16021
16021
  resolve(value) {
16022
16022
  callPuppeteer.args.delete(seq);
16023
- resolve12(value);
16023
+ resolve13(value);
16024
16024
  },
16025
16025
  reject(value) {
16026
16026
  callPuppeteer.args.delete(seq);
@@ -19683,8 +19683,8 @@ var init_Input2 = __esm({
19683
19683
  if (typeof delay === "number") {
19684
19684
  await Promise.all(actions);
19685
19685
  actions.length = 0;
19686
- await new Promise((resolve12) => {
19687
- setTimeout(resolve12, delay);
19686
+ await new Promise((resolve13) => {
19687
+ setTimeout(resolve13, delay);
19688
19688
  });
19689
19689
  }
19690
19690
  actions.push(this.up({ ...options, clickCount }));
@@ -19704,9 +19704,9 @@ var init_Input2 = __esm({
19704
19704
  });
19705
19705
  }
19706
19706
  async drag(start, target) {
19707
- const promise = new Promise((resolve12) => {
19707
+ const promise = new Promise((resolve13) => {
19708
19708
  this.#client.once("Input.dragIntercepted", (event) => {
19709
- return resolve12(event.data);
19709
+ return resolve13(event.data);
19710
19710
  });
19711
19711
  });
19712
19712
  await this.move(start.x, start.y);
@@ -19747,8 +19747,8 @@ var init_Input2 = __esm({
19747
19747
  await this.dragEnter(target, data);
19748
19748
  await this.dragOver(target, data);
19749
19749
  if (delay) {
19750
- await new Promise((resolve12) => {
19751
- return setTimeout(resolve12, delay);
19750
+ await new Promise((resolve13) => {
19751
+ return setTimeout(resolve13, delay);
19752
19752
  });
19753
19753
  }
19754
19754
  await this.drop(target, data);
@@ -20632,9 +20632,9 @@ var init_Page2 = __esm({
20632
20632
  async captureHeapSnapshot(options) {
20633
20633
  const { createWriteStream: createWriteStream3 } = environment.value.fs;
20634
20634
  const stream2 = createWriteStream3(options.path);
20635
- const streamPromise = new Promise((resolve12, reject) => {
20635
+ const streamPromise = new Promise((resolve13, reject) => {
20636
20636
  stream2.on("error", reject);
20637
- stream2.on("finish", resolve12);
20637
+ stream2.on("finish", resolve13);
20638
20638
  });
20639
20639
  const client = this.#primaryTargetClient;
20640
20640
  await client.send("HeapProfiler.enable");
@@ -22276,10 +22276,10 @@ var init_BrowserWebSocketTransport = __esm({
22276
22276
  "../../node_modules/.bun/puppeteer-core@24.40.0/node_modules/puppeteer-core/lib/esm/puppeteer/common/BrowserWebSocketTransport.js"() {
22277
22277
  BrowserWebSocketTransport = class _BrowserWebSocketTransport {
22278
22278
  static create(url) {
22279
- return new Promise((resolve12, reject) => {
22279
+ return new Promise((resolve13, reject) => {
22280
22280
  const ws = new WebSocket(url);
22281
22281
  ws.addEventListener("open", () => {
22282
- return resolve12(new _BrowserWebSocketTransport(ws));
22282
+ return resolve13(new _BrowserWebSocketTransport(ws));
22283
22283
  });
22284
22284
  ws.addEventListener("error", reject);
22285
22285
  });
@@ -25201,11 +25201,11 @@ var require_BrowsingContextProcessor = __commonJS({
25201
25201
  }
25202
25202
  const parentCdpClient = context2.cdpTarget.parentCdpClient;
25203
25203
  try {
25204
- const detachedFromTargetPromise = new Promise((resolve12) => {
25204
+ const detachedFromTargetPromise = new Promise((resolve13) => {
25205
25205
  const onContextDestroyed = (event) => {
25206
25206
  if (event.targetId === params.context) {
25207
25207
  parentCdpClient.off("Target.detachedFromTarget", onContextDestroyed);
25208
- resolve12();
25208
+ resolve13();
25209
25209
  }
25210
25210
  };
25211
25211
  parentCdpClient.on("Target.detachedFromTarget", onContextDestroyed);
@@ -26568,7 +26568,7 @@ var require_ActionDispatcher = __commonJS({
26568
26568
  }
26569
26569
  }
26570
26570
  const promises = [
26571
- new Promise((resolve12) => setTimeout(resolve12, this.#tickDuration))
26571
+ new Promise((resolve13) => setTimeout(resolve13, this.#tickDuration))
26572
26572
  ];
26573
26573
  for (const option of options) {
26574
26574
  promises.push(this.#dispatchAction(option));
@@ -27169,8 +27169,8 @@ var require_Mutex = __commonJS({
27169
27169
  acquire() {
27170
27170
  const state = { resolved: false };
27171
27171
  if (this.#locked) {
27172
- return new Promise((resolve12) => {
27173
- this.#acquirers.push(() => resolve12(this.#release.bind(this, state)));
27172
+ return new Promise((resolve13) => {
27173
+ this.#acquirers.push(() => resolve13(this.#release.bind(this, state)));
27174
27174
  });
27175
27175
  }
27176
27176
  this.#locked = true;
@@ -27181,12 +27181,12 @@ var require_Mutex = __commonJS({
27181
27181
  throw new Error("Cannot release more than once.");
27182
27182
  }
27183
27183
  state.resolved = true;
27184
- const resolve12 = this.#acquirers.shift();
27185
- if (!resolve12) {
27184
+ const resolve13 = this.#acquirers.shift();
27185
+ if (!resolve13) {
27186
27186
  this.#locked = false;
27187
27187
  return;
27188
27188
  }
27189
- resolve12();
27189
+ resolve13();
27190
27190
  }
27191
27191
  async run(action) {
27192
27192
  const release = await this.acquire();
@@ -28368,8 +28368,8 @@ var require_ChannelProxy = __commonJS({
28368
28368
  * in the queue.
28369
28369
  */
28370
28370
  async getMessage() {
28371
- const onMessage = queue.length > 0 ? Promise.resolve() : new Promise((resolve12) => {
28372
- queueNonEmptyResolver = resolve12;
28371
+ const onMessage = queue.length > 0 ? Promise.resolve() : new Promise((resolve13) => {
28372
+ queueNonEmptyResolver = resolve13;
28373
28373
  });
28374
28374
  await onMessage;
28375
28375
  return queue.shift();
@@ -28474,7 +28474,7 @@ var require_ChannelProxy = __commonJS({
28474
28474
  functionDeclaration: String((id) => {
28475
28475
  const w = window;
28476
28476
  if (w[id] === void 0) {
28477
- return new Promise((resolve12) => w[id] = resolve12);
28477
+ return new Promise((resolve13) => w[id] = resolve13);
28478
28478
  }
28479
28479
  const channelProxy = w[id];
28480
28480
  delete w[id];
@@ -29975,8 +29975,8 @@ var require_Deferred = __commonJS({
29975
29975
  return this.#result;
29976
29976
  }
29977
29977
  constructor() {
29978
- this.#promise = new Promise((resolve12, reject) => {
29979
- this.#resolve = resolve12;
29978
+ this.#promise = new Promise((resolve13, reject) => {
29979
+ this.#resolve = resolve13;
29980
29980
  this.#reject = reject;
29981
29981
  });
29982
29982
  this.#promise.catch((_error) => {
@@ -34820,11 +34820,11 @@ var require_BrowsingContextStorage = __commonJS({
34820
34820
  if (this.#contexts.has(browsingContextId)) {
34821
34821
  return Promise.resolve(this.getContext(browsingContextId));
34822
34822
  }
34823
- return new Promise((resolve12) => {
34823
+ return new Promise((resolve13) => {
34824
34824
  const listener = (event) => {
34825
34825
  if (event.browsingContext.id === browsingContextId) {
34826
34826
  this.#eventEmitter.off("added", listener);
34827
- resolve12(event.browsingContext);
34827
+ resolve13(event.browsingContext);
34828
34828
  }
34829
34829
  };
34830
34830
  this.#eventEmitter.on("added", listener);
@@ -38406,8 +38406,8 @@ var init_ExposedFunction = __esm({
38406
38406
  const functionDeclaration = stringifyFunction(interpolateFunction((callback) => {
38407
38407
  Object.assign(globalThis, {
38408
38408
  [PLACEHOLDER("name")]: function(...args) {
38409
- return new Promise((resolve12, reject) => {
38410
- callback([resolve12, reject, args]);
38409
+ return new Promise((resolve13, reject) => {
38410
+ callback([resolve13, reject, args]);
38411
38411
  });
38412
38412
  }
38413
38413
  });
@@ -38495,8 +38495,8 @@ var init_ExposedFunction = __esm({
38495
38495
  return;
38496
38496
  }
38497
38497
  try {
38498
- await dataHandle.evaluate(([resolve12], result2) => {
38499
- resolve12(result2);
38498
+ await dataHandle.evaluate(([resolve13], result2) => {
38499
+ resolve13(result2);
38500
38500
  }, result);
38501
38501
  } catch (error) {
38502
38502
  debugError(error);
@@ -46577,7 +46577,7 @@ var init_NodeWebSocketTransport = __esm({
46577
46577
  init_version();
46578
46578
  NodeWebSocketTransport = class _NodeWebSocketTransport {
46579
46579
  static create(url, headers) {
46580
- return new Promise((resolve12, reject) => {
46580
+ return new Promise((resolve13, reject) => {
46581
46581
  const ws = new wrapper_default(url, [], {
46582
46582
  followRedirects: true,
46583
46583
  perMessageDeflate: false,
@@ -46590,7 +46590,7 @@ var init_NodeWebSocketTransport = __esm({
46590
46590
  }
46591
46591
  });
46592
46592
  ws.addEventListener("open", () => {
46593
- return resolve12(new _NodeWebSocketTransport(ws));
46593
+ return resolve13(new _NodeWebSocketTransport(ws));
46594
46594
  });
46595
46595
  ws.addEventListener("error", reject);
46596
46596
  });
@@ -49651,8 +49651,8 @@ var require_helpers = __commonJS({
49651
49651
  function req(url, opts = {}) {
49652
49652
  const href = typeof url === "string" ? url : url.href;
49653
49653
  const req2 = (href.startsWith("https:") ? https2 : http2).request(url, opts);
49654
- const promise = new Promise((resolve12, reject) => {
49655
- req2.once("response", resolve12).once("error", reject).end();
49654
+ const promise = new Promise((resolve13, reject) => {
49655
+ req2.once("response", resolve13).once("error", reject).end();
49656
49656
  });
49657
49657
  req2.then = promise.then.bind(promise);
49658
49658
  return req2;
@@ -50029,7 +50029,7 @@ var require_parse_proxy_response = __commonJS({
50029
50029
  var debug_1 = __importDefault2(require_src());
50030
50030
  var debug6 = (0, debug_1.default)("https-proxy-agent:parse-proxy-response");
50031
50031
  function parseProxyResponse(socket) {
50032
- return new Promise((resolve12, reject) => {
50032
+ return new Promise((resolve13, reject) => {
50033
50033
  let buffersLength = 0;
50034
50034
  const buffers = [];
50035
50035
  function read() {
@@ -50095,7 +50095,7 @@ var require_parse_proxy_response = __commonJS({
50095
50095
  }
50096
50096
  debug6("got proxy server response: %o %o", firstLine, headers);
50097
50097
  cleanup();
50098
- resolve12({
50098
+ resolve13({
50099
50099
  connect: {
50100
50100
  statusCode,
50101
50101
  statusText,
@@ -53353,11 +53353,11 @@ var require_socksclient = __commonJS({
53353
53353
  "use strict";
53354
53354
  var __awaiter3 = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
53355
53355
  function adopt(value) {
53356
- return value instanceof P ? value : new P(function(resolve12) {
53357
- resolve12(value);
53356
+ return value instanceof P ? value : new P(function(resolve13) {
53357
+ resolve13(value);
53358
53358
  });
53359
53359
  }
53360
- return new (P || (P = Promise))(function(resolve12, reject) {
53360
+ return new (P || (P = Promise))(function(resolve13, reject) {
53361
53361
  function fulfilled(value) {
53362
53362
  try {
53363
53363
  step(generator.next(value));
@@ -53373,7 +53373,7 @@ var require_socksclient = __commonJS({
53373
53373
  }
53374
53374
  }
53375
53375
  function step(result) {
53376
- result.done ? resolve12(result.value) : adopt(result.value).then(fulfilled, rejected);
53376
+ result.done ? resolve13(result.value) : adopt(result.value).then(fulfilled, rejected);
53377
53377
  }
53378
53378
  step((generator = generator.apply(thisArg, _arguments || [])).next());
53379
53379
  });
@@ -53407,13 +53407,13 @@ var require_socksclient = __commonJS({
53407
53407
  * @returns { Promise }
53408
53408
  */
53409
53409
  static createConnection(options, callback) {
53410
- return new Promise((resolve12, reject) => {
53410
+ return new Promise((resolve13, reject) => {
53411
53411
  try {
53412
53412
  (0, helpers_1.validateSocksClientOptions)(options, ["connect"]);
53413
53413
  } catch (err) {
53414
53414
  if (typeof callback === "function") {
53415
53415
  callback(err);
53416
- return resolve12(err);
53416
+ return resolve13(err);
53417
53417
  } else {
53418
53418
  return reject(err);
53419
53419
  }
@@ -53424,16 +53424,16 @@ var require_socksclient = __commonJS({
53424
53424
  client.removeAllListeners();
53425
53425
  if (typeof callback === "function") {
53426
53426
  callback(null, info);
53427
- resolve12(info);
53427
+ resolve13(info);
53428
53428
  } else {
53429
- resolve12(info);
53429
+ resolve13(info);
53430
53430
  }
53431
53431
  });
53432
53432
  client.once("error", (err) => {
53433
53433
  client.removeAllListeners();
53434
53434
  if (typeof callback === "function") {
53435
53435
  callback(err);
53436
- resolve12(err);
53436
+ resolve13(err);
53437
53437
  } else {
53438
53438
  reject(err);
53439
53439
  }
@@ -53450,13 +53450,13 @@ var require_socksclient = __commonJS({
53450
53450
  * @returns { Promise }
53451
53451
  */
53452
53452
  static createConnectionChain(options, callback) {
53453
- return new Promise((resolve12, reject) => __awaiter3(this, void 0, void 0, function* () {
53453
+ return new Promise((resolve13, reject) => __awaiter3(this, void 0, void 0, function* () {
53454
53454
  try {
53455
53455
  (0, helpers_1.validateSocksClientChainOptions)(options);
53456
53456
  } catch (err) {
53457
53457
  if (typeof callback === "function") {
53458
53458
  callback(err);
53459
- return resolve12(err);
53459
+ return resolve13(err);
53460
53460
  } else {
53461
53461
  return reject(err);
53462
53462
  }
@@ -53482,14 +53482,14 @@ var require_socksclient = __commonJS({
53482
53482
  }
53483
53483
  if (typeof callback === "function") {
53484
53484
  callback(null, { socket: sock });
53485
- resolve12({ socket: sock });
53485
+ resolve13({ socket: sock });
53486
53486
  } else {
53487
- resolve12({ socket: sock });
53487
+ resolve13({ socket: sock });
53488
53488
  }
53489
53489
  } catch (err) {
53490
53490
  if (typeof callback === "function") {
53491
53491
  callback(err);
53492
- resolve12(err);
53492
+ resolve13(err);
53493
53493
  } else {
53494
53494
  reject(err);
53495
53495
  }
@@ -54173,12 +54173,12 @@ var require_dist4 = __commonJS({
54173
54173
  let { host } = opts;
54174
54174
  const { port, lookup: lookupFn = dns.lookup } = opts;
54175
54175
  if (shouldLookup) {
54176
- host = await new Promise((resolve12, reject) => {
54176
+ host = await new Promise((resolve13, reject) => {
54177
54177
  lookupFn(host, {}, (err, res) => {
54178
54178
  if (err) {
54179
54179
  reject(err);
54180
54180
  } else {
54181
- resolve12(res);
54181
+ resolve13(res);
54182
54182
  }
54183
54183
  });
54184
54184
  });
@@ -55363,7 +55363,7 @@ var require_netUtils = __commonJS({
55363
55363
  return `${socket.remoteAddress}:${socket.remotePort}`;
55364
55364
  }
55365
55365
  function upgradeSocket(socket, options) {
55366
- return new Promise((resolve12, reject) => {
55366
+ return new Promise((resolve13, reject) => {
55367
55367
  const tlsOptions = Object.assign({}, options, {
55368
55368
  socket
55369
55369
  });
@@ -55373,7 +55373,7 @@ var require_netUtils = __commonJS({
55373
55373
  reject(tlsSocket.authorizationError);
55374
55374
  } else {
55375
55375
  tlsSocket.removeAllListeners("error");
55376
- resolve12(tlsSocket);
55376
+ resolve13(tlsSocket);
55377
55377
  }
55378
55378
  }).once("error", (error) => {
55379
55379
  reject(error);
@@ -55468,7 +55468,7 @@ var require_transfer = __commonJS({
55468
55468
  };
55469
55469
  }
55470
55470
  function connectForPassiveTransfer(host, port, ftp) {
55471
- return new Promise((resolve12, reject) => {
55471
+ return new Promise((resolve13, reject) => {
55472
55472
  let socket = ftp._newSocket();
55473
55473
  const handleConnErr = function(err) {
55474
55474
  err.message = "Can't open data connection in passive mode: " + err.message;
@@ -55496,7 +55496,7 @@ var require_transfer = __commonJS({
55496
55496
  socket.removeListener("error", handleConnErr);
55497
55497
  socket.removeListener("timeout", handleTimeout);
55498
55498
  ftp.dataSocket = socket;
55499
- resolve12();
55499
+ resolve13();
55500
55500
  });
55501
55501
  });
55502
55502
  }
@@ -57894,7 +57894,7 @@ var require_util2 = __commonJS({
57894
57894
  return path12;
57895
57895
  }
57896
57896
  exports.normalize = normalize2;
57897
- function join16(aRoot, aPath) {
57897
+ function join17(aRoot, aPath) {
57898
57898
  if (aRoot === "") {
57899
57899
  aRoot = ".";
57900
57900
  }
@@ -57926,7 +57926,7 @@ var require_util2 = __commonJS({
57926
57926
  }
57927
57927
  return joined;
57928
57928
  }
57929
- exports.join = join16;
57929
+ exports.join = join17;
57930
57930
  exports.isAbsolute = function(aPath) {
57931
57931
  return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
57932
57932
  };
@@ -58099,7 +58099,7 @@ var require_util2 = __commonJS({
58099
58099
  parsed.path = parsed.path.substring(0, index + 1);
58100
58100
  }
58101
58101
  }
58102
- sourceURL = join16(urlGenerate(parsed), sourceURL);
58102
+ sourceURL = join17(urlGenerate(parsed), sourceURL);
58103
58103
  }
58104
58104
  return normalize2(sourceURL);
58105
58105
  }
@@ -59901,7 +59901,7 @@ var require_escodegen = __commonJS({
59901
59901
  function noEmptySpace() {
59902
59902
  return space ? space : " ";
59903
59903
  }
59904
- function join16(left2, right2) {
59904
+ function join17(left2, right2) {
59905
59905
  var leftSource, rightSource, leftCharCode, rightCharCode;
59906
59906
  leftSource = toSourceNodeWhenNeeded(left2).toString();
59907
59907
  if (leftSource.length === 0) {
@@ -60232,8 +60232,8 @@ var require_escodegen = __commonJS({
60232
60232
  } else {
60233
60233
  result.push(that.generateExpression(stmt.left, Precedence.Call, E_TTT));
60234
60234
  }
60235
- result = join16(result, operator);
60236
- result = [join16(
60235
+ result = join17(result, operator);
60236
+ result = [join17(
60237
60237
  result,
60238
60238
  that.generateExpression(stmt.right, Precedence.Assignment, E_TTT)
60239
60239
  ), ")"];
@@ -60376,11 +60376,11 @@ var require_escodegen = __commonJS({
60376
60376
  var result, fragment;
60377
60377
  result = ["class"];
60378
60378
  if (stmt.id) {
60379
- result = join16(result, this.generateExpression(stmt.id, Precedence.Sequence, E_TTT));
60379
+ result = join17(result, this.generateExpression(stmt.id, Precedence.Sequence, E_TTT));
60380
60380
  }
60381
60381
  if (stmt.superClass) {
60382
- fragment = join16("extends", this.generateExpression(stmt.superClass, Precedence.Unary, E_TTT));
60383
- result = join16(result, fragment);
60382
+ fragment = join17("extends", this.generateExpression(stmt.superClass, Precedence.Unary, E_TTT));
60383
+ result = join17(result, fragment);
60384
60384
  }
60385
60385
  result.push(space);
60386
60386
  result.push(this.generateStatement(stmt.body, S_TFFT));
@@ -60393,9 +60393,9 @@ var require_escodegen = __commonJS({
60393
60393
  return escapeDirective(stmt.directive) + this.semicolon(flags);
60394
60394
  },
60395
60395
  DoWhileStatement: function(stmt, flags) {
60396
- var result = join16("do", this.maybeBlock(stmt.body, S_TFFF));
60396
+ var result = join17("do", this.maybeBlock(stmt.body, S_TFFF));
60397
60397
  result = this.maybeBlockSuffix(stmt.body, result);
60398
- return join16(result, [
60398
+ return join17(result, [
60399
60399
  "while" + space + "(",
60400
60400
  this.generateExpression(stmt.test, Precedence.Sequence, E_TTT),
60401
60401
  ")" + this.semicolon(flags)
@@ -60431,11 +60431,11 @@ var require_escodegen = __commonJS({
60431
60431
  ExportDefaultDeclaration: function(stmt, flags) {
60432
60432
  var result = ["export"], bodyFlags;
60433
60433
  bodyFlags = flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF;
60434
- result = join16(result, "default");
60434
+ result = join17(result, "default");
60435
60435
  if (isStatement(stmt.declaration)) {
60436
- result = join16(result, this.generateStatement(stmt.declaration, bodyFlags));
60436
+ result = join17(result, this.generateStatement(stmt.declaration, bodyFlags));
60437
60437
  } else {
60438
- result = join16(result, this.generateExpression(stmt.declaration, Precedence.Assignment, E_TTT) + this.semicolon(flags));
60438
+ result = join17(result, this.generateExpression(stmt.declaration, Precedence.Assignment, E_TTT) + this.semicolon(flags));
60439
60439
  }
60440
60440
  return result;
60441
60441
  },
@@ -60443,15 +60443,15 @@ var require_escodegen = __commonJS({
60443
60443
  var result = ["export"], bodyFlags, that = this;
60444
60444
  bodyFlags = flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF;
60445
60445
  if (stmt.declaration) {
60446
- return join16(result, this.generateStatement(stmt.declaration, bodyFlags));
60446
+ return join17(result, this.generateStatement(stmt.declaration, bodyFlags));
60447
60447
  }
60448
60448
  if (stmt.specifiers) {
60449
60449
  if (stmt.specifiers.length === 0) {
60450
- result = join16(result, "{" + space + "}");
60450
+ result = join17(result, "{" + space + "}");
60451
60451
  } else if (stmt.specifiers[0].type === Syntax.ExportBatchSpecifier) {
60452
- result = join16(result, this.generateExpression(stmt.specifiers[0], Precedence.Sequence, E_TTT));
60452
+ result = join17(result, this.generateExpression(stmt.specifiers[0], Precedence.Sequence, E_TTT));
60453
60453
  } else {
60454
- result = join16(result, "{");
60454
+ result = join17(result, "{");
60455
60455
  withIndent(function(indent2) {
60456
60456
  var i, iz;
60457
60457
  result.push(newline);
@@ -60469,7 +60469,7 @@ var require_escodegen = __commonJS({
60469
60469
  result.push(base + "}");
60470
60470
  }
60471
60471
  if (stmt.source) {
60472
- result = join16(result, [
60472
+ result = join17(result, [
60473
60473
  "from" + space,
60474
60474
  // ModuleSpecifier
60475
60475
  this.generateExpression(stmt.source, Precedence.Sequence, E_TTT),
@@ -60557,7 +60557,7 @@ var require_escodegen = __commonJS({
60557
60557
  ];
60558
60558
  cursor = 0;
60559
60559
  if (stmt.specifiers[cursor].type === Syntax.ImportDefaultSpecifier) {
60560
- result = join16(result, [
60560
+ result = join17(result, [
60561
60561
  this.generateExpression(stmt.specifiers[cursor], Precedence.Sequence, E_TTT)
60562
60562
  ]);
60563
60563
  ++cursor;
@@ -60567,7 +60567,7 @@ var require_escodegen = __commonJS({
60567
60567
  result.push(",");
60568
60568
  }
60569
60569
  if (stmt.specifiers[cursor].type === Syntax.ImportNamespaceSpecifier) {
60570
- result = join16(result, [
60570
+ result = join17(result, [
60571
60571
  space,
60572
60572
  this.generateExpression(stmt.specifiers[cursor], Precedence.Sequence, E_TTT)
60573
60573
  ]);
@@ -60596,7 +60596,7 @@ var require_escodegen = __commonJS({
60596
60596
  }
60597
60597
  }
60598
60598
  }
60599
- result = join16(result, [
60599
+ result = join17(result, [
60600
60600
  "from" + space,
60601
60601
  // ModuleSpecifier
60602
60602
  this.generateExpression(stmt.source, Precedence.Sequence, E_TTT),
@@ -60650,7 +60650,7 @@ var require_escodegen = __commonJS({
60650
60650
  return result;
60651
60651
  },
60652
60652
  ThrowStatement: function(stmt, flags) {
60653
- return [join16(
60653
+ return [join17(
60654
60654
  "throw",
60655
60655
  this.generateExpression(stmt.argument, Precedence.Sequence, E_TTT)
60656
60656
  ), this.semicolon(flags)];
@@ -60661,7 +60661,7 @@ var require_escodegen = __commonJS({
60661
60661
  result = this.maybeBlockSuffix(stmt.block, result);
60662
60662
  if (stmt.handlers) {
60663
60663
  for (i = 0, iz = stmt.handlers.length; i < iz; ++i) {
60664
- result = join16(result, this.generateStatement(stmt.handlers[i], S_TFFF));
60664
+ result = join17(result, this.generateStatement(stmt.handlers[i], S_TFFF));
60665
60665
  if (stmt.finalizer || i + 1 !== iz) {
60666
60666
  result = this.maybeBlockSuffix(stmt.handlers[i].body, result);
60667
60667
  }
@@ -60669,7 +60669,7 @@ var require_escodegen = __commonJS({
60669
60669
  } else {
60670
60670
  guardedHandlers = stmt.guardedHandlers || [];
60671
60671
  for (i = 0, iz = guardedHandlers.length; i < iz; ++i) {
60672
- result = join16(result, this.generateStatement(guardedHandlers[i], S_TFFF));
60672
+ result = join17(result, this.generateStatement(guardedHandlers[i], S_TFFF));
60673
60673
  if (stmt.finalizer || i + 1 !== iz) {
60674
60674
  result = this.maybeBlockSuffix(guardedHandlers[i].body, result);
60675
60675
  }
@@ -60677,13 +60677,13 @@ var require_escodegen = __commonJS({
60677
60677
  if (stmt.handler) {
60678
60678
  if (Array.isArray(stmt.handler)) {
60679
60679
  for (i = 0, iz = stmt.handler.length; i < iz; ++i) {
60680
- result = join16(result, this.generateStatement(stmt.handler[i], S_TFFF));
60680
+ result = join17(result, this.generateStatement(stmt.handler[i], S_TFFF));
60681
60681
  if (stmt.finalizer || i + 1 !== iz) {
60682
60682
  result = this.maybeBlockSuffix(stmt.handler[i].body, result);
60683
60683
  }
60684
60684
  }
60685
60685
  } else {
60686
- result = join16(result, this.generateStatement(stmt.handler, S_TFFF));
60686
+ result = join17(result, this.generateStatement(stmt.handler, S_TFFF));
60687
60687
  if (stmt.finalizer) {
60688
60688
  result = this.maybeBlockSuffix(stmt.handler.body, result);
60689
60689
  }
@@ -60691,7 +60691,7 @@ var require_escodegen = __commonJS({
60691
60691
  }
60692
60692
  }
60693
60693
  if (stmt.finalizer) {
60694
- result = join16(result, ["finally", this.maybeBlock(stmt.finalizer, S_TFFF)]);
60694
+ result = join17(result, ["finally", this.maybeBlock(stmt.finalizer, S_TFFF)]);
60695
60695
  }
60696
60696
  return result;
60697
60697
  },
@@ -60725,7 +60725,7 @@ var require_escodegen = __commonJS({
60725
60725
  withIndent(function() {
60726
60726
  if (stmt.test) {
60727
60727
  result = [
60728
- join16("case", that.generateExpression(stmt.test, Precedence.Sequence, E_TTT)),
60728
+ join17("case", that.generateExpression(stmt.test, Precedence.Sequence, E_TTT)),
60729
60729
  ":"
60730
60730
  ];
60731
60731
  } else {
@@ -60773,9 +60773,9 @@ var require_escodegen = __commonJS({
60773
60773
  result.push(this.maybeBlock(stmt.consequent, S_TFFF));
60774
60774
  result = this.maybeBlockSuffix(stmt.consequent, result);
60775
60775
  if (stmt.alternate.type === Syntax.IfStatement) {
60776
- result = join16(result, ["else ", this.generateStatement(stmt.alternate, bodyFlags)]);
60776
+ result = join17(result, ["else ", this.generateStatement(stmt.alternate, bodyFlags)]);
60777
60777
  } else {
60778
- result = join16(result, join16("else", this.maybeBlock(stmt.alternate, bodyFlags)));
60778
+ result = join17(result, join17("else", this.maybeBlock(stmt.alternate, bodyFlags)));
60779
60779
  }
60780
60780
  } else {
60781
60781
  result.push(this.maybeBlock(stmt.consequent, bodyFlags));
@@ -60876,7 +60876,7 @@ var require_escodegen = __commonJS({
60876
60876
  },
60877
60877
  ReturnStatement: function(stmt, flags) {
60878
60878
  if (stmt.argument) {
60879
- return [join16(
60879
+ return [join17(
60880
60880
  "return",
60881
60881
  this.generateExpression(stmt.argument, Precedence.Sequence, E_TTT)
60882
60882
  ), this.semicolon(flags)];
@@ -60965,14 +60965,14 @@ var require_escodegen = __commonJS({
60965
60965
  if (leftSource.charCodeAt(leftSource.length - 1) === 47 && esutils.code.isIdentifierPartES5(expr.operator.charCodeAt(0))) {
60966
60966
  result = [fragment, noEmptySpace(), expr.operator];
60967
60967
  } else {
60968
- result = join16(fragment, expr.operator);
60968
+ result = join17(fragment, expr.operator);
60969
60969
  }
60970
60970
  fragment = this.generateExpression(expr.right, rightPrecedence, flags);
60971
60971
  if (expr.operator === "/" && fragment.toString().charAt(0) === "/" || expr.operator.slice(-1) === "<" && fragment.toString().slice(0, 3) === "!--") {
60972
60972
  result.push(noEmptySpace());
60973
60973
  result.push(fragment);
60974
60974
  } else {
60975
- result = join16(result, fragment);
60975
+ result = join17(result, fragment);
60976
60976
  }
60977
60977
  if (expr.operator === "in" && !(flags & F_ALLOW_IN)) {
60978
60978
  return ["(", result, ")"];
@@ -61012,7 +61012,7 @@ var require_escodegen = __commonJS({
61012
61012
  var result, length, i, iz, itemFlags;
61013
61013
  length = expr["arguments"].length;
61014
61014
  itemFlags = flags & F_ALLOW_UNPARATH_NEW && !parentheses && length === 0 ? E_TFT : E_TFF;
61015
- result = join16(
61015
+ result = join17(
61016
61016
  "new",
61017
61017
  this.generateExpression(expr.callee, Precedence.New, itemFlags)
61018
61018
  );
@@ -61062,11 +61062,11 @@ var require_escodegen = __commonJS({
61062
61062
  var result, fragment, rightCharCode, leftSource, leftCharCode;
61063
61063
  fragment = this.generateExpression(expr.argument, Precedence.Unary, E_TTT);
61064
61064
  if (space === "") {
61065
- result = join16(expr.operator, fragment);
61065
+ result = join17(expr.operator, fragment);
61066
61066
  } else {
61067
61067
  result = [expr.operator];
61068
61068
  if (expr.operator.length > 2) {
61069
- result = join16(result, fragment);
61069
+ result = join17(result, fragment);
61070
61070
  } else {
61071
61071
  leftSource = toSourceNodeWhenNeeded(result).toString();
61072
61072
  leftCharCode = leftSource.charCodeAt(leftSource.length - 1);
@@ -61089,7 +61089,7 @@ var require_escodegen = __commonJS({
61089
61089
  result = "yield";
61090
61090
  }
61091
61091
  if (expr.argument) {
61092
- result = join16(
61092
+ result = join17(
61093
61093
  result,
61094
61094
  this.generateExpression(expr.argument, Precedence.Yield, E_TTT)
61095
61095
  );
@@ -61097,7 +61097,7 @@ var require_escodegen = __commonJS({
61097
61097
  return parenthesize(result, Precedence.Yield, precedence);
61098
61098
  },
61099
61099
  AwaitExpression: function(expr, precedence, flags) {
61100
- var result = join16(
61100
+ var result = join17(
61101
61101
  expr.all ? "await*" : "await",
61102
61102
  this.generateExpression(expr.argument, Precedence.Await, E_TTT)
61103
61103
  );
@@ -61180,11 +61180,11 @@ var require_escodegen = __commonJS({
61180
61180
  var result, fragment;
61181
61181
  result = ["class"];
61182
61182
  if (expr.id) {
61183
- result = join16(result, this.generateExpression(expr.id, Precedence.Sequence, E_TTT));
61183
+ result = join17(result, this.generateExpression(expr.id, Precedence.Sequence, E_TTT));
61184
61184
  }
61185
61185
  if (expr.superClass) {
61186
- fragment = join16("extends", this.generateExpression(expr.superClass, Precedence.Unary, E_TTT));
61187
- result = join16(result, fragment);
61186
+ fragment = join17("extends", this.generateExpression(expr.superClass, Precedence.Unary, E_TTT));
61187
+ result = join17(result, fragment);
61188
61188
  }
61189
61189
  result.push(space);
61190
61190
  result.push(this.generateStatement(expr.body, S_TFFT));
@@ -61199,7 +61199,7 @@ var require_escodegen = __commonJS({
61199
61199
  }
61200
61200
  if (expr.kind === "get" || expr.kind === "set") {
61201
61201
  fragment = [
61202
- join16(expr.kind, this.generatePropertyKey(expr.key, expr.computed)),
61202
+ join17(expr.kind, this.generatePropertyKey(expr.key, expr.computed)),
61203
61203
  this.generateFunctionBody(expr.value)
61204
61204
  ];
61205
61205
  } else {
@@ -61209,7 +61209,7 @@ var require_escodegen = __commonJS({
61209
61209
  this.generateFunctionBody(expr.value)
61210
61210
  ];
61211
61211
  }
61212
- return join16(result, fragment);
61212
+ return join17(result, fragment);
61213
61213
  },
61214
61214
  Property: function(expr, precedence, flags) {
61215
61215
  if (expr.kind === "get" || expr.kind === "set") {
@@ -61404,7 +61404,7 @@ var require_escodegen = __commonJS({
61404
61404
  for (i = 0, iz = expr.blocks.length; i < iz; ++i) {
61405
61405
  fragment = that.generateExpression(expr.blocks[i], Precedence.Sequence, E_TTT);
61406
61406
  if (i > 0 || extra.moz.comprehensionExpressionStartsWithAssignment) {
61407
- result = join16(result, fragment);
61407
+ result = join17(result, fragment);
61408
61408
  } else {
61409
61409
  result.push(fragment);
61410
61410
  }
@@ -61412,13 +61412,13 @@ var require_escodegen = __commonJS({
61412
61412
  });
61413
61413
  }
61414
61414
  if (expr.filter) {
61415
- result = join16(result, "if" + space);
61415
+ result = join17(result, "if" + space);
61416
61416
  fragment = this.generateExpression(expr.filter, Precedence.Sequence, E_TTT);
61417
- result = join16(result, ["(", fragment, ")"]);
61417
+ result = join17(result, ["(", fragment, ")"]);
61418
61418
  }
61419
61419
  if (!extra.moz.comprehensionExpressionStartsWithAssignment) {
61420
61420
  fragment = this.generateExpression(expr.body, Precedence.Assignment, E_TTT);
61421
- result = join16(result, fragment);
61421
+ result = join17(result, fragment);
61422
61422
  }
61423
61423
  result.push(expr.type === Syntax.GeneratorExpression ? ")" : "]");
61424
61424
  return result;
@@ -61434,8 +61434,8 @@ var require_escodegen = __commonJS({
61434
61434
  } else {
61435
61435
  fragment = this.generateExpression(expr.left, Precedence.Call, E_TTT);
61436
61436
  }
61437
- fragment = join16(fragment, expr.of ? "of" : "in");
61438
- fragment = join16(fragment, this.generateExpression(expr.right, Precedence.Sequence, E_TTT));
61437
+ fragment = join17(fragment, expr.of ? "of" : "in");
61438
+ fragment = join17(fragment, this.generateExpression(expr.right, Precedence.Sequence, E_TTT));
61439
61439
  return ["for" + space + "(", fragment, ")"];
61440
61440
  },
61441
61441
  SpreadElement: function(expr, precedence, flags) {
@@ -67965,11 +67965,11 @@ function __metadata(metadataKey, metadataValue) {
67965
67965
  }
67966
67966
  function __awaiter2(thisArg, _arguments, P, generator) {
67967
67967
  function adopt(value) {
67968
- return value instanceof P ? value : new P(function(resolve12) {
67969
- resolve12(value);
67968
+ return value instanceof P ? value : new P(function(resolve13) {
67969
+ resolve13(value);
67970
67970
  });
67971
67971
  }
67972
- return new (P || (P = Promise))(function(resolve12, reject) {
67972
+ return new (P || (P = Promise))(function(resolve13, reject) {
67973
67973
  function fulfilled(value) {
67974
67974
  try {
67975
67975
  step(generator.next(value));
@@ -67985,7 +67985,7 @@ function __awaiter2(thisArg, _arguments, P, generator) {
67985
67985
  }
67986
67986
  }
67987
67987
  function step(result) {
67988
- result.done ? resolve12(result.value) : adopt(result.value).then(fulfilled, rejected);
67988
+ result.done ? resolve13(result.value) : adopt(result.value).then(fulfilled, rejected);
67989
67989
  }
67990
67990
  step((generator = generator.apply(thisArg, _arguments || [])).next());
67991
67991
  });
@@ -68176,14 +68176,14 @@ function __asyncValues2(o) {
68176
68176
  }, i);
68177
68177
  function verb(n) {
68178
68178
  i[n] = o[n] && function(v) {
68179
- return new Promise(function(resolve12, reject) {
68180
- v = o[n](v), settle(resolve12, reject, v.done, v.value);
68179
+ return new Promise(function(resolve13, reject) {
68180
+ v = o[n](v), settle(resolve13, reject, v.done, v.value);
68181
68181
  });
68182
68182
  };
68183
68183
  }
68184
- function settle(resolve12, reject, d, v) {
68184
+ function settle(resolve13, reject, d, v) {
68185
68185
  Promise.resolve(v).then(function(v2) {
68186
- resolve12({ value: v2, done: d });
68186
+ resolve13({ value: v2, done: d });
68187
68187
  }, reject);
68188
68188
  }
68189
68189
  }
@@ -71736,12 +71736,12 @@ var require_util3 = __commonJS({
71736
71736
  exports.isGMT = exports.dnsLookup = void 0;
71737
71737
  var dns_1 = __require("dns");
71738
71738
  function dnsLookup(host, opts) {
71739
- return new Promise((resolve12, reject) => {
71739
+ return new Promise((resolve13, reject) => {
71740
71740
  (0, dns_1.lookup)(host, opts, (err, res) => {
71741
71741
  if (err) {
71742
71742
  reject(err);
71743
71743
  } else {
71744
- resolve12(res);
71744
+ resolve13(res);
71745
71745
  }
71746
71746
  });
71747
71747
  });
@@ -72106,10 +72106,10 @@ var require_myIpAddress = __commonJS({
72106
72106
  var ip_1 = require_ip();
72107
72107
  var net_1 = __importDefault2(__require("net"));
72108
72108
  async function myIpAddress() {
72109
- return new Promise((resolve12, reject) => {
72109
+ return new Promise((resolve13, reject) => {
72110
72110
  const socket = net_1.default.connect({ host: "8.8.8.8", port: 53 });
72111
72111
  const onError = () => {
72112
- resolve12(ip_1.ip.address());
72112
+ resolve13(ip_1.ip.address());
72113
72113
  };
72114
72114
  socket.once("error", onError);
72115
72115
  socket.once("connect", () => {
@@ -72117,9 +72117,9 @@ var require_myIpAddress = __commonJS({
72117
72117
  const addr = socket.address();
72118
72118
  socket.destroy();
72119
72119
  if (typeof addr === "string") {
72120
- resolve12(addr);
72120
+ resolve13(addr);
72121
72121
  } else if (addr.address) {
72122
- resolve12(addr.address);
72122
+ resolve13(addr.address);
72123
72123
  } else {
72124
72124
  reject(new Error("Expected a `string`"));
72125
72125
  }
@@ -72697,8 +72697,8 @@ var require_deferred_promise = __commonJS({
72697
72697
  this.context = args.context;
72698
72698
  this.owner = args.context.runtime;
72699
72699
  this.handle = args.promiseHandle;
72700
- this.settled = new Promise((resolve12) => {
72701
- this.onSettled = resolve12;
72700
+ this.settled = new Promise((resolve13) => {
72701
+ this.onSettled = resolve13;
72702
72702
  });
72703
72703
  this.resolveHandle = args.resolveHandle;
72704
72704
  this.rejectHandle = args.rejectHandle;
@@ -73219,13 +73219,13 @@ var require_context = __commonJS({
73219
73219
  if (vmResolveResult.error) {
73220
73220
  return Promise.resolve(vmResolveResult);
73221
73221
  }
73222
- return new Promise((resolve12) => {
73222
+ return new Promise((resolve13) => {
73223
73223
  lifetime_1.Scope.withScope((scope) => {
73224
73224
  const resolveHandle = scope.manage(this.newFunction("resolve", (value) => {
73225
- resolve12({ value: value && value.dup() });
73225
+ resolve13({ value: value && value.dup() });
73226
73226
  }));
73227
73227
  const rejectHandle = scope.manage(this.newFunction("reject", (error) => {
73228
- resolve12({ error: error && error.dup() });
73228
+ resolve13({ error: error && error.dup() });
73229
73229
  }));
73230
73230
  const promiseHandle = scope.manage(vmResolveResult.value);
73231
73231
  const promiseThenHandle = scope.manage(this.getProp(promiseHandle, "then"));
@@ -75600,13 +75600,13 @@ import * as http from "node:http";
75600
75600
  import * as https from "node:https";
75601
75601
  import { URL as URL2, urlToHttpOptions } from "node:url";
75602
75602
  function headHttpRequest(url) {
75603
- return new Promise((resolve12) => {
75603
+ return new Promise((resolve13) => {
75604
75604
  const request3 = httpRequest(url, "HEAD", (response) => {
75605
75605
  response.resume();
75606
- resolve12(response.statusCode === 200);
75606
+ resolve13(response.statusCode === 200);
75607
75607
  }, false);
75608
75608
  request3.on("error", () => {
75609
- resolve12(false);
75609
+ resolve13(false);
75610
75610
  });
75611
75611
  });
75612
75612
  }
@@ -75634,7 +75634,7 @@ function httpRequest(url, method, response, keepAlive = true) {
75634
75634
  return request3;
75635
75635
  }
75636
75636
  function downloadFile(url, destinationPath, progressCallback) {
75637
- return new Promise((resolve12, reject) => {
75637
+ return new Promise((resolve13, reject) => {
75638
75638
  let downloadedBytes = 0;
75639
75639
  let totalBytes = 0;
75640
75640
  function onData(chunk) {
@@ -75650,7 +75650,7 @@ function downloadFile(url, destinationPath, progressCallback) {
75650
75650
  }
75651
75651
  const file = createWriteStream(destinationPath);
75652
75652
  file.on("close", () => {
75653
- return resolve12();
75653
+ return resolve13();
75654
75654
  });
75655
75655
  file.on("error", (error) => {
75656
75656
  return reject(error);
@@ -75675,7 +75675,7 @@ async function getJSON(url) {
75675
75675
  }
75676
75676
  }
75677
75677
  function getText3(url) {
75678
- return new Promise((resolve12, reject) => {
75678
+ return new Promise((resolve13, reject) => {
75679
75679
  const request3 = httpRequest(url, "GET", (response) => {
75680
75680
  let data = "";
75681
75681
  if (response.statusCode && response.statusCode >= 400) {
@@ -75686,7 +75686,7 @@ function getText3(url) {
75686
75686
  });
75687
75687
  response.on("end", () => {
75688
75688
  try {
75689
- return resolve12(String(data));
75689
+ return resolve13(String(data));
75690
75690
  } catch {
75691
75691
  return reject(new Error(`Failed to read text response from ${url}`));
75692
75692
  }
@@ -77078,7 +77078,7 @@ var init_launch = __esm({
77078
77078
  if (opts.onExit) {
77079
77079
  this.#onExitHook = opts.onExit;
77080
77080
  }
77081
- this.#browserProcessExiting = new Promise((resolve12, reject) => {
77081
+ this.#browserProcessExiting = new Promise((resolve13, reject) => {
77082
77082
  this.#browserProcess.once("exit", async () => {
77083
77083
  debugLaunch(`Browser process ${this.#browserProcess.pid} onExit`);
77084
77084
  this.#clearListeners();
@@ -77089,7 +77089,7 @@ var init_launch = __esm({
77089
77089
  reject(err);
77090
77090
  return;
77091
77091
  }
77092
- resolve12();
77092
+ resolve13();
77093
77093
  });
77094
77094
  });
77095
77095
  }
@@ -77205,7 +77205,7 @@ Error cause: ${isErrorLike2(error) ? error.stack : error}`);
77205
77205
  return [...this.#logs];
77206
77206
  }
77207
77207
  waitForLineOutput(regex, timeout2 = 0) {
77208
- return new Promise((resolve12, reject) => {
77208
+ return new Promise((resolve13, reject) => {
77209
77209
  const onClose = (errorOrCode) => {
77210
77210
  cleanup();
77211
77211
  reject(new Error([
@@ -77241,7 +77241,7 @@ Error cause: ${isErrorLike2(error) ? error.stack : error}`);
77241
77241
  return;
77242
77242
  }
77243
77243
  cleanup();
77244
- resolve12(match2[1]);
77244
+ resolve13(match2[1]);
77245
77245
  }
77246
77246
  });
77247
77247
  }
@@ -77710,7 +77710,7 @@ var require_get_stream = __commonJS({
77710
77710
  };
77711
77711
  const { maxBuffer } = options;
77712
77712
  let stream2;
77713
- await new Promise((resolve12, reject) => {
77713
+ await new Promise((resolve13, reject) => {
77714
77714
  const rejectPromise = (error) => {
77715
77715
  if (error && stream2.getBufferedLength() <= BufferConstants.MAX_LENGTH) {
77716
77716
  error.bufferedData = stream2.getBufferedValue();
@@ -77722,7 +77722,7 @@ var require_get_stream = __commonJS({
77722
77722
  rejectPromise(error);
77723
77723
  return;
77724
77724
  }
77725
- resolve12();
77725
+ resolve13();
77726
77726
  });
77727
77727
  stream2.on("data", () => {
77728
77728
  if (stream2.getBufferedLength() > maxBuffer) {
@@ -79011,7 +79011,7 @@ var require_extract_zip = __commonJS({
79011
79011
  debug6("opening", this.zipPath, "with opts", this.opts);
79012
79012
  this.zipfile = await openZip(this.zipPath, { lazyEntries: true });
79013
79013
  this.canceled = false;
79014
- return new Promise((resolve12, reject) => {
79014
+ return new Promise((resolve13, reject) => {
79015
79015
  this.zipfile.on("error", (err) => {
79016
79016
  this.canceled = true;
79017
79017
  reject(err);
@@ -79020,7 +79020,7 @@ var require_extract_zip = __commonJS({
79020
79020
  this.zipfile.on("close", () => {
79021
79021
  if (!this.canceled) {
79022
79022
  debug6("zip extraction complete");
79023
- resolve12();
79023
+ resolve13();
79024
79024
  }
79025
79025
  });
79026
79026
  this.zipfile.on("entry", async (entry) => {
@@ -80277,8 +80277,8 @@ var require_streamx = __commonJS({
80277
80277
  return this;
80278
80278
  },
80279
80279
  next() {
80280
- return new Promise(function(resolve12, reject) {
80281
- promiseResolve = resolve12;
80280
+ return new Promise(function(resolve13, reject) {
80281
+ promiseResolve = resolve13;
80282
80282
  promiseReject = reject;
80283
80283
  const data = stream2.read();
80284
80284
  if (data !== null) ondata(data);
@@ -80308,11 +80308,11 @@ var require_streamx = __commonJS({
80308
80308
  }
80309
80309
  function destroy(err) {
80310
80310
  stream2.destroy(err);
80311
- return new Promise((resolve12, reject) => {
80312
- if (stream2._duplexState & DESTROYED) return resolve12({ value: void 0, done: true });
80311
+ return new Promise((resolve13, reject) => {
80312
+ if (stream2._duplexState & DESTROYED) return resolve13({ value: void 0, done: true });
80313
80313
  stream2.once("close", function() {
80314
80314
  if (err) reject(err);
80315
- else resolve12({ value: void 0, done: true });
80315
+ else resolve13({ value: void 0, done: true });
80316
80316
  });
80317
80317
  });
80318
80318
  }
@@ -80356,8 +80356,8 @@ var require_streamx = __commonJS({
80356
80356
  const writes = pending + (ws._duplexState & WRITE_WRITING ? 1 : 0);
80357
80357
  if (writes === 0) return Promise.resolve(true);
80358
80358
  if (state.drains === null) state.drains = [];
80359
- return new Promise((resolve12) => {
80360
- state.drains.push({ writes, resolve: resolve12 });
80359
+ return new Promise((resolve13) => {
80360
+ state.drains.push({ writes, resolve: resolve13 });
80361
80361
  });
80362
80362
  }
80363
80363
  write(data) {
@@ -80462,10 +80462,10 @@ var require_streamx = __commonJS({
80462
80462
  cb(null);
80463
80463
  }
80464
80464
  function pipelinePromise(...streams) {
80465
- return new Promise((resolve12, reject) => {
80465
+ return new Promise((resolve13, reject) => {
80466
80466
  return pipeline(...streams, (err) => {
80467
80467
  if (err) return reject(err);
80468
- resolve12();
80468
+ resolve13();
80469
80469
  });
80470
80470
  });
80471
80471
  }
@@ -81120,16 +81120,16 @@ var require_extract = __commonJS({
81120
81120
  entryCallback = null;
81121
81121
  cb(err);
81122
81122
  }
81123
- function onnext(resolve12, reject) {
81123
+ function onnext(resolve13, reject) {
81124
81124
  if (error) {
81125
81125
  return reject(error);
81126
81126
  }
81127
81127
  if (entryStream) {
81128
- resolve12({ value: entryStream, done: false });
81128
+ resolve13({ value: entryStream, done: false });
81129
81129
  entryStream = null;
81130
81130
  return;
81131
81131
  }
81132
- promiseResolve = resolve12;
81132
+ promiseResolve = resolve13;
81133
81133
  promiseReject = reject;
81134
81134
  consumeCallback(null);
81135
81135
  if (extract._finished && promiseResolve) {
@@ -81157,11 +81157,11 @@ var require_extract = __commonJS({
81157
81157
  function destroy(err) {
81158
81158
  extract.destroy(err);
81159
81159
  consumeCallback(err);
81160
- return new Promise((resolve12, reject) => {
81161
- if (extract.destroyed) return resolve12({ value: void 0, done: true });
81160
+ return new Promise((resolve13, reject) => {
81161
+ if (extract.destroyed) return resolve13({ value: void 0, done: true });
81162
81162
  extract.once("close", function() {
81163
81163
  if (err) reject(err);
81164
- else resolve12({ value: void 0, done: true });
81164
+ else resolve13({ value: void 0, done: true });
81165
81165
  });
81166
81166
  });
81167
81167
  }
@@ -86137,12 +86137,12 @@ var init_yargs_factory = __esm({
86137
86137
  async getCompletion(args, done) {
86138
86138
  argsert("<array> [function]", [args, done], arguments.length);
86139
86139
  if (!done) {
86140
- return new Promise((resolve12, reject) => {
86140
+ return new Promise((resolve13, reject) => {
86141
86141
  __classPrivateFieldGet2(this, _YargsInstance_completion, "f").getCompletion(args, (err, completions) => {
86142
86142
  if (err)
86143
86143
  reject(err);
86144
86144
  else
86145
- resolve12(completions);
86145
+ resolve13(completions);
86146
86146
  });
86147
86147
  });
86148
86148
  } else {
@@ -87597,9 +87597,9 @@ async function getConnectionTransport(options) {
87597
87597
  throw new Error("Could not detect required browser platform");
87598
87598
  }
87599
87599
  const { convertPuppeteerChannelToBrowsersChannel: convertPuppeteerChannelToBrowsersChannel2 } = await Promise.resolve().then(() => (init_LaunchOptions(), LaunchOptions_exports));
87600
- const { join: join16 } = await import("node:path");
87600
+ const { join: join17 } = await import("node:path");
87601
87601
  const userDataDir = resolveDefaultUserDataDir3(Browser4.CHROME, platform, convertPuppeteerChannelToBrowsersChannel2(options.channel));
87602
- const portPath = join16(userDataDir, "DevToolsActivePort");
87602
+ const portPath = join17(userDataDir, "DevToolsActivePort");
87603
87603
  try {
87604
87604
  const fileContent = await environment.value.fs.promises.readFile(portPath, "ascii");
87605
87605
  const [rawPort, rawPath] = fileContent.split("\n").map((line) => {
@@ -88943,8 +88943,8 @@ var init_ScreenRecorder = __esm({
88943
88943
  static {
88944
88944
  const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
88945
88945
  __esDecorate23(this, _private_writeFrame_descriptor = { value: __setFunctionName6(async function(buffer) {
88946
- const error = await new Promise((resolve12) => {
88947
- this.#process.stdin.write(buffer, resolve12);
88946
+ const error = await new Promise((resolve13) => {
88947
+ this.#process.stdin.write(buffer, resolve13);
88948
88948
  });
88949
88949
  if (error) {
88950
88950
  console.log(`ffmpeg failed to write: ${error.message}.`);
@@ -89134,8 +89134,8 @@ var init_ScreenRecorder = __esm({
89134
89134
  const [buffer, timestamp] = await this.#lastFrame;
89135
89135
  await Promise.all(Array(Math.max(1, Math.round(this.#fps * (performance.now() - timestamp) / 1e3))).fill(buffer).map(this.#writeFrame.bind(this)));
89136
89136
  this.#process.stdin.end();
89137
- await new Promise((resolve12) => {
89138
- this.#process.once("close", resolve12);
89137
+ await new Promise((resolve13) => {
89138
+ this.#process.once("close", resolve13);
89139
89139
  });
89140
89140
  }
89141
89141
  /**
@@ -93032,8 +93032,8 @@ var CustomElementRegistry = class {
93032
93032
  } : (element) => element.localName === localName;
93033
93033
  registry.set(localName, { Class, check });
93034
93034
  if (waiting.has(localName)) {
93035
- for (const resolve12 of waiting.get(localName))
93036
- resolve12(Class);
93035
+ for (const resolve13 of waiting.get(localName))
93036
+ resolve13(Class);
93037
93037
  waiting.delete(localName);
93038
93038
  }
93039
93039
  ownerDocument.querySelectorAll(
@@ -93073,13 +93073,13 @@ var CustomElementRegistry = class {
93073
93073
  */
93074
93074
  whenDefined(localName) {
93075
93075
  const { registry, waiting } = this;
93076
- return new Promise((resolve12) => {
93076
+ return new Promise((resolve13) => {
93077
93077
  if (registry.has(localName))
93078
- resolve12(registry.get(localName).Class);
93078
+ resolve13(registry.get(localName).Class);
93079
93079
  else {
93080
93080
  if (!waiting.has(localName))
93081
93081
  waiting.set(localName, []);
93082
- waiting.get(localName).push(resolve12);
93082
+ waiting.get(localName).push(resolve13);
93083
93083
  }
93084
93084
  });
93085
93085
  }
@@ -98907,7 +98907,7 @@ function buildChromeArgs(options, config2) {
98907
98907
 
98908
98908
  // ../engine/src/services/frameCapture.ts
98909
98909
  import { existsSync as existsSync4, mkdirSync, writeFileSync } from "fs";
98910
- import { join as join4 } from "path";
98910
+ import { join as join5 } from "path";
98911
98911
 
98912
98912
  // ../core/src/parsers/gsapParser.ts
98913
98913
  var GSAP_METHODS = /* @__PURE__ */ new Set(["set", "to", "from", "fromTo"]);
@@ -99063,10 +99063,14 @@ function hasAttr(tag, attr) {
99063
99063
  function injectAttr(tag, attr, value) {
99064
99064
  return tag.replace(/>$/, ` ${attr}="${value}">`);
99065
99065
  }
99066
- function compileTag(tag, isVideo) {
99066
+ function compileTag(tag, isVideo, generateId) {
99067
99067
  let result = tag;
99068
99068
  let unresolved = null;
99069
- const id = getAttr(result, "id");
99069
+ let id = getAttr(result, "id");
99070
+ if (!id) {
99071
+ id = `${isVideo ? "hf-video" : "hf-audio"}-${generateId()}`;
99072
+ result = injectAttr(result, "id", id);
99073
+ }
99070
99074
  const startStr = getAttr(result, "data-start");
99071
99075
  const start = startStr !== null ? parseFloat(startStr) : 0;
99072
99076
  const mediaStartStr = getAttr(result, "data-media-start");
@@ -99093,13 +99097,15 @@ function compileTag(tag, isVideo) {
99093
99097
  }
99094
99098
  function compileTimingAttrs(html) {
99095
99099
  const unresolved = [];
99100
+ let nextVideoId = 0;
99101
+ let nextAudioId = 0;
99096
99102
  html = html.replace(/<video[^>]*>/gi, (match2) => {
99097
- const { tag, unresolved: u } = compileTag(match2, true);
99103
+ const { tag, unresolved: u } = compileTag(match2, true, () => nextVideoId++);
99098
99104
  if (u) unresolved.push(u);
99099
99105
  return tag;
99100
99106
  });
99101
99107
  html = html.replace(/<audio[^>]*>/gi, (match2) => {
99102
- const { tag, unresolved: u } = compileTag(match2, false);
99108
+ const { tag, unresolved: u } = compileTag(match2, false, () => nextAudioId++);
99103
99109
  if (u) unresolved.push(u);
99104
99110
  return tag;
99105
99111
  });
@@ -99182,80 +99188,175 @@ function clampDurations(html, clamps) {
99182
99188
  return html;
99183
99189
  }
99184
99190
 
99185
- // ../core/src/lint/hyperframeLinter.ts
99191
+ // ../core/src/lint/utils.ts
99186
99192
  var TAG_PATTERN = /<([a-z][\w:-]*)(\s[^<>]*?)?>/gi;
99187
99193
  var STYLE_BLOCK_PATTERN = /<style\b([^>]*)>([\s\S]*?)<\/style>/gi;
99188
99194
  var SCRIPT_BLOCK_PATTERN = /<script\b([^>]*)>([\s\S]*?)<\/script>/gi;
99189
99195
  var COMPOSITION_ID_IN_CSS_PATTERN = /\[data-composition-id=["']([^"']+)["']\]/g;
99190
99196
  var TIMELINE_REGISTRY_INIT_PATTERN = /window\.__timelines\s*=\s*window\.__timelines\s*\|\|\s*\{\}|window\.__timelines\s*=\s*\{\}|window\.__timelines\s*\?\?=\s*\{\}/i;
99191
99197
  var TIMELINE_REGISTRY_ASSIGN_PATTERN = /window\.__timelines\[[^\]]+\]\s*=/i;
99192
- var INVALID_SCRIPT_CLOSE_PATTERN = /<script[^>]*>[\s\S]*?<\s*\/\s*script(?!>)/i;
99193
99198
  var WINDOW_TIMELINE_ASSIGN_PATTERN = /window\.__timelines\[\s*["']([^"']+)["']\s*\]\s*=\s*([A-Za-z_$][\w$]*)/i;
99194
- var META_GSAP_KEYS = /* @__PURE__ */ new Set(["duration", "ease", "repeat", "yoyo", "overwrite", "delay"]);
99195
- function lintHyperframeHtml(html, options = {}) {
99199
+ var INVALID_SCRIPT_CLOSE_PATTERN = /<script[^>]*>[\s\S]*?<\s*\/\s*script(?!>)/i;
99200
+ function extractOpenTags(source2) {
99201
+ const tags = [];
99202
+ let match2;
99203
+ const pattern = new RegExp(TAG_PATTERN.source, TAG_PATTERN.flags);
99204
+ while ((match2 = pattern.exec(source2)) !== null) {
99205
+ const raw2 = match2[0];
99206
+ if (raw2.startsWith("</") || raw2.startsWith("<!")) continue;
99207
+ tags.push({
99208
+ raw: raw2,
99209
+ name: (match2[1] || "").toLowerCase(),
99210
+ attrs: match2[2] || "",
99211
+ index: match2.index
99212
+ });
99213
+ }
99214
+ return tags;
99215
+ }
99216
+ function extractBlocks(source2, pattern) {
99217
+ const blocks = [];
99218
+ let match2;
99219
+ const p = new RegExp(pattern.source, pattern.flags);
99220
+ while ((match2 = p.exec(source2)) !== null) {
99221
+ blocks.push({
99222
+ attrs: match2[1] || "",
99223
+ content: match2[2] || "",
99224
+ raw: match2[0],
99225
+ index: match2.index
99226
+ });
99227
+ }
99228
+ return blocks;
99229
+ }
99230
+ function findRootTag(source2) {
99231
+ const bodyMatch = source2.match(/<body\b[^>]*>([\s\S]*?)<\/body>/i);
99232
+ const bodyContent = bodyMatch ? bodyMatch[1] ?? source2 : source2;
99233
+ const bodyTags = extractOpenTags(bodyContent);
99234
+ for (const tag of bodyTags) {
99235
+ if (["script", "style", "meta", "link", "title"].includes(tag.name)) continue;
99236
+ return tag;
99237
+ }
99238
+ return null;
99239
+ }
99240
+ function readAttr(tagSource, attr) {
99241
+ if (!tagSource) return null;
99242
+ const escaped = attr.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
99243
+ const match2 = tagSource.match(new RegExp(`\\b${escaped}\\s*=\\s*["']([^"']+)["']`, "i"));
99244
+ return match2?.[1] || null;
99245
+ }
99246
+ function collectCompositionIds(tags) {
99247
+ const ids = /* @__PURE__ */ new Set();
99248
+ for (const tag of tags) {
99249
+ const compId = readAttr(tag.raw, "data-composition-id");
99250
+ if (compId) ids.add(compId);
99251
+ }
99252
+ return ids;
99253
+ }
99254
+ function extractCompositionIdsFromCss(css) {
99255
+ const ids = /* @__PURE__ */ new Set();
99256
+ let match2;
99257
+ const pattern = new RegExp(
99258
+ COMPOSITION_ID_IN_CSS_PATTERN.source,
99259
+ COMPOSITION_ID_IN_CSS_PATTERN.flags
99260
+ );
99261
+ while ((match2 = pattern.exec(css)) !== null) {
99262
+ if (match2[1]) ids.add(match2[1]);
99263
+ }
99264
+ return [...ids];
99265
+ }
99266
+ function getInlineScriptSyntaxError(source2) {
99267
+ if (!source2.trim()) return null;
99268
+ try {
99269
+ new Function(source2);
99270
+ return null;
99271
+ } catch (error) {
99272
+ if (error instanceof Error) return error.message;
99273
+ return String(error);
99274
+ }
99275
+ }
99276
+ function isMediaTag(tagName19) {
99277
+ return tagName19 === "video" || tagName19 === "audio" || tagName19 === "img";
99278
+ }
99279
+ function truncateSnippet(value, maxLength = 220) {
99280
+ const normalized = value.replace(/\s+/g, " ").trim();
99281
+ if (!normalized) return void 0;
99282
+ if (normalized.length <= maxLength) return normalized;
99283
+ return `${normalized.slice(0, maxLength - 3)}...`;
99284
+ }
99285
+
99286
+ // ../core/src/lint/context.ts
99287
+ function buildLintContext(html, options = {}) {
99196
99288
  let source2 = html || "";
99197
99289
  const templateMatch = source2.match(/<template[^>]*>([\s\S]*)<\/template>/i);
99198
99290
  if (templateMatch?.[1]) source2 = templateMatch[1];
99199
- const filePath = options.filePath;
99200
- const findings = [];
99201
- const seen = /* @__PURE__ */ new Set();
99202
- const pushFinding = (finding) => {
99203
- const dedupeKey = [
99204
- finding.code,
99205
- finding.severity,
99206
- finding.selector || "",
99207
- finding.elementId || "",
99208
- finding.message
99209
- ].join("|");
99210
- if (seen.has(dedupeKey)) {
99211
- return;
99212
- }
99213
- seen.add(dedupeKey);
99214
- findings.push(filePath ? { ...finding, file: filePath } : finding);
99215
- };
99216
99291
  const tags = extractOpenTags(source2);
99217
99292
  const styles = extractBlocks(source2, STYLE_BLOCK_PATTERN);
99218
99293
  const scripts = extractBlocks(source2, SCRIPT_BLOCK_PATTERN);
99219
99294
  const compositionIds = collectCompositionIds(tags);
99220
99295
  const rootTag = findRootTag(source2);
99221
99296
  const rootCompositionId = readAttr(rootTag?.raw || "", "data-composition-id");
99222
- if (!rootTag || !readAttr(rootTag.raw, "data-composition-id")) {
99223
- pushFinding({
99224
- code: "root_missing_composition_id",
99225
- severity: "error",
99226
- message: "Root composition is missing `data-composition-id`.",
99227
- elementId: rootTag ? readAttr(rootTag.raw, "id") || void 0 : void 0,
99228
- fixHint: "Add a stable `data-composition-id` to the entry composition wrapper.",
99229
- snippet: truncateSnippet(rootTag?.raw || "")
99230
- });
99231
- }
99232
- if (!rootTag || !readAttr(rootTag.raw, "data-width") || !readAttr(rootTag.raw, "data-height")) {
99233
- pushFinding({
99234
- code: "root_missing_dimensions",
99235
- severity: "error",
99236
- message: "Root composition is missing `data-width` or `data-height`.",
99237
- elementId: rootTag ? readAttr(rootTag.raw, "id") || void 0 : void 0,
99238
- fixHint: "Set numeric `data-width` and `data-height` on the entry composition root.",
99239
- snippet: truncateSnippet(rootTag?.raw || "")
99240
- });
99241
- }
99242
- if (!TIMELINE_REGISTRY_INIT_PATTERN.test(source2) && !TIMELINE_REGISTRY_ASSIGN_PATTERN.test(source2)) {
99243
- pushFinding({
99244
- code: "missing_timeline_registry",
99245
- severity: "error",
99246
- message: "Missing `window.__timelines` registration.",
99247
- fixHint: "Register each composition timeline on `window.__timelines[compositionId]`."
99248
- });
99249
- }
99250
- if (TIMELINE_REGISTRY_ASSIGN_PATTERN.test(source2) && !TIMELINE_REGISTRY_INIT_PATTERN.test(source2)) {
99251
- pushFinding({
99252
- code: "timeline_registry_missing_init",
99253
- severity: "error",
99254
- message: "`window.__timelines[\u2026] = \u2026` is used without initializing `window.__timelines` first.",
99255
- fixHint: "Add `window.__timelines = window.__timelines || {};` before any timeline assignment."
99256
- });
99257
- }
99258
- {
99297
+ return {
99298
+ source: source2,
99299
+ tags,
99300
+ styles,
99301
+ scripts,
99302
+ compositionIds,
99303
+ rootTag,
99304
+ rootCompositionId,
99305
+ options
99306
+ };
99307
+ }
99308
+
99309
+ // ../core/src/lint/rules/core.ts
99310
+ var coreRules = [
99311
+ // root_missing_composition_id + root_missing_dimensions
99312
+ ({ rootTag }) => {
99313
+ const findings = [];
99314
+ if (!rootTag || !readAttr(rootTag.raw, "data-composition-id")) {
99315
+ findings.push({
99316
+ code: "root_missing_composition_id",
99317
+ severity: "error",
99318
+ message: "Root composition is missing `data-composition-id`.",
99319
+ elementId: rootTag ? readAttr(rootTag.raw, "id") || void 0 : void 0,
99320
+ fixHint: "Add a stable `data-composition-id` to the entry composition wrapper.",
99321
+ snippet: truncateSnippet(rootTag?.raw || "")
99322
+ });
99323
+ }
99324
+ if (!rootTag || !readAttr(rootTag.raw, "data-width") || !readAttr(rootTag.raw, "data-height")) {
99325
+ findings.push({
99326
+ code: "root_missing_dimensions",
99327
+ severity: "error",
99328
+ message: "Root composition is missing `data-width` or `data-height`.",
99329
+ elementId: rootTag ? readAttr(rootTag.raw, "id") || void 0 : void 0,
99330
+ fixHint: "Set numeric `data-width` and `data-height` on the entry composition root.",
99331
+ snippet: truncateSnippet(rootTag?.raw || "")
99332
+ });
99333
+ }
99334
+ return findings;
99335
+ },
99336
+ // missing_timeline_registry + timeline_registry_missing_init
99337
+ ({ source: source2 }) => {
99338
+ const findings = [];
99339
+ if (!TIMELINE_REGISTRY_INIT_PATTERN.test(source2) && !TIMELINE_REGISTRY_ASSIGN_PATTERN.test(source2)) {
99340
+ findings.push({
99341
+ code: "missing_timeline_registry",
99342
+ severity: "error",
99343
+ message: "Missing `window.__timelines` registration.",
99344
+ fixHint: "Register each composition timeline on `window.__timelines[compositionId]`."
99345
+ });
99346
+ }
99347
+ if (TIMELINE_REGISTRY_ASSIGN_PATTERN.test(source2) && !TIMELINE_REGISTRY_INIT_PATTERN.test(source2)) {
99348
+ findings.push({
99349
+ code: "timeline_registry_missing_init",
99350
+ severity: "error",
99351
+ message: "`window.__timelines[\u2026] = \u2026` is used without initializing `window.__timelines` first.",
99352
+ fixHint: "Add `window.__timelines = window.__timelines || {};` before any timeline assignment."
99353
+ });
99354
+ }
99355
+ return findings;
99356
+ },
99357
+ // timeline_id_mismatch
99358
+ ({ source: source2 }) => {
99359
+ const findings = [];
99259
99360
  const htmlCompIds = /* @__PURE__ */ new Set();
99260
99361
  const timelineRegKeys = /* @__PURE__ */ new Set();
99261
99362
  const compIdRe = /data-composition-id\s*=\s*["']([^"']+)["']/gi;
@@ -99269,7 +99370,7 @@ function lintHyperframeHtml(html, options = {}) {
99269
99370
  }
99270
99371
  for (const key2 of timelineRegKeys) {
99271
99372
  if (!htmlCompIds.has(key2)) {
99272
- pushFinding({
99373
+ findings.push({
99273
99374
  code: "timeline_id_mismatch",
99274
99375
  severity: "error",
99275
99376
  message: `Timeline registered as "${key2}" but no element has data-composition-id="${key2}". The runtime cannot auto-nest this timeline.`,
@@ -99277,261 +99378,194 @@ function lintHyperframeHtml(html, options = {}) {
99277
99378
  });
99278
99379
  }
99279
99380
  }
99280
- }
99281
- if (INVALID_SCRIPT_CLOSE_PATTERN.test(source2)) {
99282
- pushFinding({
99283
- code: "invalid_inline_script_syntax",
99284
- severity: "error",
99285
- message: "Detected malformed inline `<script>` closing syntax.",
99286
- fixHint: "Close inline scripts with a valid `</script>` tag."
99287
- });
99288
- }
99289
- for (const script of scripts) {
99290
- const attrs = script.attrs || "";
99291
- if (/\bsrc\s*=/.test(attrs) || /\btype\s*=\s*["']application\/json["']/.test(attrs)) {
99292
- continue;
99293
- }
99294
- const syntaxError = getInlineScriptSyntaxError(script.content);
99295
- if (!syntaxError) {
99296
- continue;
99297
- }
99298
- pushFinding({
99299
- code: "invalid_inline_script_syntax",
99300
- severity: "error",
99301
- message: `Inline script has invalid syntax: ${syntaxError}`,
99302
- fixHint: "Fix the inline script syntax before render verification.",
99303
- snippet: truncateSnippet(script.content)
99304
- });
99305
- }
99306
- for (const tag of tags) {
99307
- const src = readAttr(tag.raw, "data-composition-src");
99308
- if (!src) {
99309
- continue;
99310
- }
99311
- const compId = readAttr(tag.raw, "data-composition-id");
99312
- if (compId) {
99313
- continue;
99314
- }
99315
- pushFinding({
99316
- code: "host_missing_composition_id",
99317
- severity: "error",
99318
- message: `Composition host for "${src}" is missing \`data-composition-id\`.`,
99319
- elementId: readAttr(tag.raw, "id") || void 0,
99320
- fixHint: "Set `data-composition-id` on every `data-composition-src` host element.",
99321
- snippet: truncateSnippet(tag.raw)
99322
- });
99323
- }
99324
- const scopedCssCompositionIds = /* @__PURE__ */ new Set();
99325
- for (const style of styles) {
99326
- for (const compId of extractCompositionIdsFromCss(style.content)) {
99327
- scopedCssCompositionIds.add(compId);
99328
- }
99329
- }
99330
- for (const compId of scopedCssCompositionIds) {
99331
- if (compositionIds.has(compId)) {
99332
- continue;
99333
- }
99334
- pushFinding({
99335
- code: "scoped_css_missing_wrapper",
99336
- severity: "warning",
99337
- message: `Scoped CSS targets composition "${compId}" but no matching wrapper exists in this HTML.`,
99338
- selector: `[data-composition-id="${compId}"]`,
99339
- fixHint: "Preserve the matching composition wrapper or align the CSS scope to an existing wrapper."
99340
- });
99341
- }
99342
- const mediaById = /* @__PURE__ */ new Map();
99343
- const mediaFingerprintCounts = /* @__PURE__ */ new Map();
99344
- for (const tag of tags) {
99345
- if (!isMediaTag(tag.name)) {
99346
- continue;
99347
- }
99348
- const elementId = readAttr(tag.raw, "id");
99349
- if (elementId) {
99350
- const existing = mediaById.get(elementId) || [];
99351
- existing.push(tag);
99352
- mediaById.set(elementId, existing);
99353
- }
99354
- const fingerprint = [
99355
- tag.name,
99356
- readAttr(tag.raw, "src") || "",
99357
- readAttr(tag.raw, "data-start") || "",
99358
- readAttr(tag.raw, "data-duration") || ""
99359
- ].join("|");
99360
- mediaFingerprintCounts.set(fingerprint, (mediaFingerprintCounts.get(fingerprint) || 0) + 1);
99361
- }
99362
- for (const [elementId, mediaTags] of mediaById) {
99363
- if (mediaTags.length < 2) {
99364
- continue;
99365
- }
99366
- pushFinding({
99367
- code: "duplicate_media_id",
99368
- severity: "error",
99369
- message: `Media id "${elementId}" is defined multiple times.`,
99370
- elementId,
99371
- fixHint: "Give each media element a unique id so preview and producer discover the same media graph.",
99372
- snippet: truncateSnippet(mediaTags[0]?.raw || "")
99373
- });
99374
- }
99375
- for (const [fingerprint, count] of mediaFingerprintCounts) {
99376
- if (count < 2) {
99377
- continue;
99378
- }
99379
- const [tagName19, src, dataStart, dataDuration] = fingerprint.split("|");
99380
- pushFinding({
99381
- code: "duplicate_media_discovery_risk",
99382
- severity: "warning",
99383
- message: `Detected ${count} matching ${tagName19} entries with the same source/start/duration.`,
99384
- fixHint: "Avoid duplicated media nodes that can be discovered twice during compilation.",
99385
- snippet: truncateSnippet(
99386
- `${tagName19} src=${src} data-start=${dataStart} data-duration=${dataDuration}`
99387
- )
99388
- });
99389
- }
99390
- const clipIds = /* @__PURE__ */ new Map();
99391
- const clipClasses = /* @__PURE__ */ new Map();
99392
- for (const tag of tags) {
99393
- const classAttr = readAttr(tag.raw, "class") || "";
99394
- const classes = classAttr.split(/\s+/).filter(Boolean);
99395
- if (!classes.includes("clip")) continue;
99396
- const id = readAttr(tag.raw, "id");
99397
- const info = { tag: tag.name, id: id || "", classes: classAttr };
99398
- if (id) clipIds.set(`#${id}`, info);
99399
- for (const cls of classes) {
99400
- if (cls !== "clip") clipClasses.set(`.${cls}`, info);
99401
- }
99402
- }
99403
- const classUsage = countClassUsage(tags);
99404
- for (const script of scripts) {
99405
- const localTimelineCompId = readRegisteredTimelineCompositionId(script.content);
99406
- const gsapWindows = extractGsapWindows(script.content);
99407
- for (let i = 0; i < gsapWindows.length; i++) {
99408
- const left2 = gsapWindows[i];
99409
- if (!left2) continue;
99410
- if (left2.end <= left2.position) {
99411
- continue;
99412
- }
99413
- for (let j = i + 1; j < gsapWindows.length; j++) {
99414
- const right2 = gsapWindows[j];
99415
- if (!right2) continue;
99416
- if (right2.end <= right2.position) {
99417
- continue;
99418
- }
99419
- if (left2.targetSelector !== right2.targetSelector) {
99420
- continue;
99421
- }
99422
- const overlapStart = Math.max(left2.position, right2.position);
99423
- const overlapEnd = Math.min(left2.end, right2.end);
99424
- if (overlapEnd <= overlapStart) {
99425
- continue;
99426
- }
99427
- if (left2.overwriteAuto || right2.overwriteAuto) {
99428
- continue;
99429
- }
99430
- const sharedProperties = left2.properties.filter((prop2) => right2.properties.includes(prop2));
99431
- if (sharedProperties.length === 0) {
99432
- continue;
99433
- }
99434
- pushFinding({
99435
- code: "overlapping_gsap_tweens",
99436
- severity: "warning",
99437
- message: `GSAP tweens overlap on "${left2.targetSelector}" for ${sharedProperties.join(", ")} between ${overlapStart.toFixed(2)}s and ${overlapEnd.toFixed(2)}s.`,
99438
- selector: left2.targetSelector,
99439
- fixHint: 'Shorten the earlier tween, move the later tween, or add `overwrite: "auto"`.',
99440
- snippet: truncateSnippet(`${left2.raw}
99441
- ${right2.raw}`)
99442
- });
99381
+ return findings;
99382
+ },
99383
+ // invalid_inline_script_syntax (malformed close tag)
99384
+ ({ source: source2 }) => {
99385
+ if (!INVALID_SCRIPT_CLOSE_PATTERN.test(source2)) return [];
99386
+ return [
99387
+ {
99388
+ code: "invalid_inline_script_syntax",
99389
+ severity: "error",
99390
+ message: "Detected malformed inline `<script>` closing syntax.",
99391
+ fixHint: "Close inline scripts with a valid `</script>` tag."
99443
99392
  }
99444
- }
99445
- for (const win of gsapWindows) {
99446
- const sel = win.targetSelector;
99447
- const clipInfo = clipIds.get(sel) || clipClasses.get(sel);
99448
- if (!clipInfo) continue;
99449
- const elDesc = `<${clipInfo.tag}${clipInfo.id ? ` id="${clipInfo.id}"` : ""} class="${clipInfo.classes}">`;
99450
- pushFinding({
99451
- code: "gsap_animates_clip_element",
99393
+ ];
99394
+ },
99395
+ // invalid_inline_script_syntax (JS parse error)
99396
+ ({ scripts }) => {
99397
+ const findings = [];
99398
+ for (const script of scripts) {
99399
+ const attrs = script.attrs || "";
99400
+ if (/\bsrc\s*=/.test(attrs) || /\btype\s*=\s*["']application\/json["']/.test(attrs)) continue;
99401
+ const syntaxError = getInlineScriptSyntaxError(script.content);
99402
+ if (!syntaxError) continue;
99403
+ findings.push({
99404
+ code: "invalid_inline_script_syntax",
99452
99405
  severity: "error",
99453
- message: `GSAP animation targets a clip element. Selector "${sel}" resolves to element ${elDesc}. The framework manages clip visibility \u2014 animate an inner wrapper instead.`,
99454
- selector: sel,
99455
- elementId: clipInfo.id || void 0,
99456
- fixHint: "Wrap content in a child <div> and target that with GSAP.",
99457
- snippet: truncateSnippet(win.raw)
99406
+ message: `Inline script has invalid syntax: ${syntaxError}`,
99407
+ fixHint: "Fix the inline script syntax before render verification.",
99408
+ snippet: truncateSnippet(script.content)
99458
99409
  });
99459
99410
  }
99460
- if (!localTimelineCompId || localTimelineCompId === rootCompositionId) {
99461
- continue;
99411
+ return findings;
99412
+ },
99413
+ // host_missing_composition_id
99414
+ ({ tags }) => {
99415
+ const findings = [];
99416
+ for (const tag of tags) {
99417
+ const src = readAttr(tag.raw, "data-composition-src");
99418
+ if (!src) continue;
99419
+ if (readAttr(tag.raw, "data-composition-id")) continue;
99420
+ findings.push({
99421
+ code: "host_missing_composition_id",
99422
+ severity: "error",
99423
+ message: `Composition host for "${src}" is missing \`data-composition-id\`.`,
99424
+ elementId: readAttr(tag.raw, "id") || void 0,
99425
+ fixHint: "Set `data-composition-id` on every `data-composition-src` host element.",
99426
+ snippet: truncateSnippet(tag.raw)
99427
+ });
99462
99428
  }
99463
- for (const win of gsapWindows) {
99464
- if (!isSuspiciousGlobalSelector(win.targetSelector)) {
99465
- continue;
99466
- }
99467
- const className = getSingleClassSelector(win.targetSelector);
99468
- if (className && (classUsage.get(className) || 0) < 2) {
99469
- continue;
99429
+ return findings;
99430
+ },
99431
+ // scoped_css_missing_wrapper
99432
+ ({ styles, compositionIds }) => {
99433
+ const findings = [];
99434
+ const scopedCssCompositionIds = /* @__PURE__ */ new Set();
99435
+ for (const style of styles) {
99436
+ for (const compId of extractCompositionIdsFromCss(style.content)) {
99437
+ scopedCssCompositionIds.add(compId);
99470
99438
  }
99471
- pushFinding({
99472
- code: "unscoped_gsap_selector",
99439
+ }
99440
+ for (const compId of scopedCssCompositionIds) {
99441
+ if (compositionIds.has(compId)) continue;
99442
+ findings.push({
99443
+ code: "scoped_css_missing_wrapper",
99473
99444
  severity: "warning",
99474
- message: `Timeline "${localTimelineCompId}" uses unscoped selector "${win.targetSelector}" that will target elements in ALL compositions when bundled, causing data loss (opacity, transforms, etc.).`,
99475
- selector: win.targetSelector,
99476
- fixHint: `Scope the selector: \`[data-composition-id="${localTimelineCompId}"] ${win.targetSelector}\` or use a unique id.`,
99477
- snippet: truncateSnippet(win.raw)
99445
+ message: `Scoped CSS targets composition "${compId}" but no matching wrapper exists in this HTML.`,
99446
+ selector: `[data-composition-id="${compId}"]`,
99447
+ fixHint: "Preserve the matching composition wrapper or align the CSS scope to an existing wrapper."
99478
99448
  });
99479
99449
  }
99450
+ return findings;
99480
99451
  }
99481
- for (const tag of tags) {
99482
- if (tag.name !== "video") continue;
99483
- const hasMuted = /\bmuted\b/i.test(tag.raw);
99484
- if (!hasMuted && readAttr(tag.raw, "data-start")) {
99485
- const elementId = readAttr(tag.raw, "id") || void 0;
99486
- pushFinding({
99487
- code: "video_missing_muted",
99452
+ ];
99453
+
99454
+ // ../core/src/lint/rules/media.ts
99455
+ var mediaRules = [
99456
+ // duplicate_media_id + duplicate_media_discovery_risk
99457
+ ({ tags }) => {
99458
+ const findings = [];
99459
+ const mediaById = /* @__PURE__ */ new Map();
99460
+ const mediaFingerprintCounts = /* @__PURE__ */ new Map();
99461
+ for (const tag of tags) {
99462
+ if (!isMediaTag(tag.name)) continue;
99463
+ const elementId = readAttr(tag.raw, "id");
99464
+ if (elementId) {
99465
+ const existing = mediaById.get(elementId) || [];
99466
+ existing.push(tag);
99467
+ mediaById.set(elementId, existing);
99468
+ }
99469
+ const fingerprint = [
99470
+ tag.name,
99471
+ readAttr(tag.raw, "src") || "",
99472
+ readAttr(tag.raw, "data-start") || "",
99473
+ readAttr(tag.raw, "data-duration") || ""
99474
+ ].join("|");
99475
+ mediaFingerprintCounts.set(fingerprint, (mediaFingerprintCounts.get(fingerprint) || 0) + 1);
99476
+ }
99477
+ for (const [elementId, mediaTags] of mediaById) {
99478
+ if (mediaTags.length < 2) continue;
99479
+ findings.push({
99480
+ code: "duplicate_media_id",
99488
99481
  severity: "error",
99489
- 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.`,
99482
+ message: `Media id "${elementId}" is defined multiple times.`,
99490
99483
  elementId,
99491
- fixHint: "Add the `muted` attribute to the <video> tag and use a separate <audio> element with the same src for audio playback.",
99492
- snippet: truncateSnippet(tag.raw)
99484
+ fixHint: "Give each media element a unique id so preview and producer discover the same media graph.",
99485
+ snippet: truncateSnippet(mediaTags[0]?.raw || "")
99493
99486
  });
99494
99487
  }
99495
- }
99496
- const timedTagPositions = [];
99497
- for (const tag of tags) {
99498
- if (tag.name === "video" || tag.name === "audio") continue;
99499
- if (readAttr(tag.raw, "data-start")) {
99500
- timedTagPositions.push({
99501
- name: tag.name,
99502
- start: tag.index,
99503
- id: readAttr(tag.raw, "id") || void 0
99488
+ for (const [fingerprint, count] of mediaFingerprintCounts) {
99489
+ if (count < 2) continue;
99490
+ const [tagName19, src, dataStart, dataDuration] = fingerprint.split("|");
99491
+ findings.push({
99492
+ code: "duplicate_media_discovery_risk",
99493
+ severity: "warning",
99494
+ message: `Detected ${count} matching ${tagName19} entries with the same source/start/duration.`,
99495
+ fixHint: "Avoid duplicated media nodes that can be discovered twice during compilation.",
99496
+ snippet: truncateSnippet(
99497
+ `${tagName19} src=${src} data-start=${dataStart} data-duration=${dataDuration}`
99498
+ )
99504
99499
  });
99505
99500
  }
99506
- }
99507
- for (const tag of tags) {
99508
- if (tag.name !== "video") continue;
99509
- if (!readAttr(tag.raw, "data-start")) continue;
99510
- for (const parent of timedTagPositions) {
99511
- if (parent.start < tag.index) {
99512
- const parentClosePattern = new RegExp(`</${parent.name}>`, "gi");
99513
- const between = source2.substring(parent.start, tag.index);
99514
- if (!parentClosePattern.test(between)) {
99515
- pushFinding({
99516
- code: "video_nested_in_timed_element",
99517
- severity: "error",
99518
- 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.`,
99519
- elementId: readAttr(tag.raw, "id") || void 0,
99520
- 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).",
99521
- snippet: truncateSnippet(tag.raw)
99522
- });
99523
- break;
99501
+ return findings;
99502
+ },
99503
+ // video_missing_muted
99504
+ ({ tags }) => {
99505
+ const findings = [];
99506
+ for (const tag of tags) {
99507
+ if (tag.name !== "video") continue;
99508
+ const hasMuted = /\bmuted\b/i.test(tag.raw);
99509
+ if (!hasMuted && readAttr(tag.raw, "data-start")) {
99510
+ const elementId = readAttr(tag.raw, "id") || void 0;
99511
+ findings.push({
99512
+ code: "video_missing_muted",
99513
+ severity: "error",
99514
+ 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.`,
99515
+ elementId,
99516
+ fixHint: "Add the `muted` attribute to the <video> tag and use a separate <audio> element with the same src for audio playback.",
99517
+ snippet: truncateSnippet(tag.raw)
99518
+ });
99519
+ }
99520
+ }
99521
+ return findings;
99522
+ },
99523
+ // video_nested_in_timed_element
99524
+ ({ source: source2, tags }) => {
99525
+ const findings = [];
99526
+ const timedTagPositions = [];
99527
+ for (const tag of tags) {
99528
+ if (tag.name === "video" || tag.name === "audio") continue;
99529
+ if (readAttr(tag.raw, "data-start")) {
99530
+ timedTagPositions.push({
99531
+ name: tag.name,
99532
+ start: tag.index,
99533
+ id: readAttr(tag.raw, "id") || void 0
99534
+ });
99535
+ }
99536
+ }
99537
+ for (const tag of tags) {
99538
+ if (tag.name !== "video") continue;
99539
+ if (!readAttr(tag.raw, "data-start")) continue;
99540
+ for (const parent of timedTagPositions) {
99541
+ if (parent.start < tag.index) {
99542
+ const parentClosePattern = new RegExp(`</${parent.name}>`, "gi");
99543
+ const between = source2.substring(parent.start, tag.index);
99544
+ if (!parentClosePattern.test(between)) {
99545
+ findings.push({
99546
+ code: "video_nested_in_timed_element",
99547
+ severity: "error",
99548
+ 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.`,
99549
+ elementId: readAttr(tag.raw, "id") || void 0,
99550
+ 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).",
99551
+ snippet: truncateSnippet(tag.raw)
99552
+ });
99553
+ break;
99554
+ }
99524
99555
  }
99525
99556
  }
99526
99557
  }
99527
- }
99528
- {
99558
+ return findings;
99559
+ },
99560
+ // self_closing_media_tag
99561
+ ({ source: source2 }) => {
99562
+ const findings = [];
99529
99563
  const selfClosingMediaRe = /<(audio|video)\b[^>]*\/>/gi;
99530
99564
  let scMatch;
99531
99565
  while ((scMatch = selfClosingMediaRe.exec(source2)) !== null) {
99532
99566
  const tagName19 = scMatch[1] || "audio";
99533
99567
  const elementId = readAttr(scMatch[0], "id") || void 0;
99534
- pushFinding({
99568
+ findings.push({
99535
99569
  code: "self_closing_media_tag",
99536
99570
  severity: "error",
99537
99571
  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.`,
@@ -99540,8 +99574,11 @@ ${right2.raw}`)
99540
99574
  snippet: truncateSnippet(scMatch[0])
99541
99575
  });
99542
99576
  }
99543
- }
99544
- {
99577
+ return findings;
99578
+ },
99579
+ // placeholder_media_url
99580
+ ({ tags }) => {
99581
+ const findings = [];
99545
99582
  const PLACEHOLDER_DOMAINS = /\b(placehold\.co|placeholder\.com|placekitten\.com|picsum\.photos|example\.com|via\.placeholder\.com|dummyimage\.com)\b/i;
99546
99583
  for (const tag of tags) {
99547
99584
  if (!isMediaTag(tag.name)) continue;
@@ -99549,7 +99586,7 @@ ${right2.raw}`)
99549
99586
  if (!src) continue;
99550
99587
  if (PLACEHOLDER_DOMAINS.test(src)) {
99551
99588
  const elementId = readAttr(tag.raw, "id") || void 0;
99552
- pushFinding({
99589
+ findings.push({
99553
99590
  code: "placeholder_media_url",
99554
99591
  severity: "error",
99555
99592
  message: `<${tag.name}${elementId ? ` id="${elementId}"` : ""}> uses a placeholder URL that will 404 at render time: ${src.slice(0, 80)}`,
@@ -99559,8 +99596,11 @@ ${right2.raw}`)
99559
99596
  });
99560
99597
  }
99561
99598
  }
99562
- }
99563
- {
99599
+ return findings;
99600
+ },
99601
+ // base64_media_prohibited
99602
+ ({ source: source2 }) => {
99603
+ const findings = [];
99564
99604
  const base64MediaRe = /src\s*=\s*["'](data:(?:audio|video)\/[^;]+;base64,([A-Za-z0-9+/=]{20,}))["']/gi;
99565
99605
  let b64Match;
99566
99606
  while ((b64Match = base64MediaRe.exec(source2)) !== null) {
@@ -99568,7 +99608,7 @@ ${right2.raw}`)
99568
99608
  const uniqueChars = new Set(sample.replace(/[A-Za-z0-9+/=]/g, (c) => c)).size;
99569
99609
  const dataSize = Math.round((b64Match[2] || "").length * 3 / 4);
99570
99610
  const isSuspicious = uniqueChars < 15 || dataSize > 1e3 && dataSize < 5e4;
99571
- pushFinding({
99611
+ findings.push({
99572
99612
  code: "base64_media_prohibited",
99573
99613
  severity: "error",
99574
99614
  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.`,
@@ -99576,331 +99616,57 @@ ${right2.raw}`)
99576
99616
  snippet: truncateSnippet((b64Match[1] ?? "").slice(0, 80) + "...")
99577
99617
  });
99578
99618
  }
99579
- }
99580
- for (const tag of tags) {
99581
- if (tag.name !== "video" && tag.name !== "audio") continue;
99582
- const hasDataStart = readAttr(tag.raw, "data-start");
99583
- const hasId = readAttr(tag.raw, "id");
99584
- const hasSrc = readAttr(tag.raw, "src");
99585
- if (hasDataStart && !hasId) {
99586
- pushFinding({
99587
- code: "media_missing_id",
99588
- severity: "error",
99589
- 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.`,
99590
- fixHint: `Add a unique id attribute: <${tag.name} id="my-${tag.name}" ...>`,
99591
- snippet: truncateSnippet(tag.raw)
99592
- });
99593
- }
99594
- if (hasDataStart && hasId && !hasSrc) {
99595
- pushFinding({
99596
- code: "media_missing_src",
99597
- severity: "error",
99598
- message: `<${tag.name} id="${hasId}"> has data-start but no src attribute. The renderer cannot load this media.`,
99599
- elementId: hasId,
99600
- fixHint: `Add a src attribute to the <${tag.name}> element directly. If using <source> children, the renderer still requires src on the parent element.`,
99601
- snippet: truncateSnippet(tag.raw)
99602
- });
99603
- }
99604
- if (readAttr(tag.raw, "preload") === "none") {
99605
- pushFinding({
99606
- code: "media_preload_none",
99607
- severity: "warning",
99608
- 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.`,
99609
- elementId: hasId || void 0,
99610
- fixHint: `Remove preload="none" or change to preload="auto". The framework manages media loading.`,
99611
- snippet: truncateSnippet(tag.raw)
99612
- });
99613
- }
99614
- }
99615
- for (const tag of tags) {
99616
- if (tag.name === "audio" || tag.name === "script" || tag.name === "style") continue;
99617
- if (!readAttr(tag.raw, "data-start")) continue;
99618
- if (readAttr(tag.raw, "data-composition-id")) continue;
99619
- if (readAttr(tag.raw, "data-composition-src")) continue;
99620
- const classAttr = readAttr(tag.raw, "class") || "";
99621
- const styleAttr = readAttr(tag.raw, "style") || "";
99622
- const hasClip = classAttr.split(/\s+/).includes("clip");
99623
- const hasHiddenStyle = /visibility\s*:\s*hidden/i.test(styleAttr) || /opacity\s*:\s*0/i.test(styleAttr);
99624
- if (!hasClip && !hasHiddenStyle) {
99625
- const elementId = readAttr(tag.raw, "id") || void 0;
99626
- pushFinding({
99627
- code: "timed_element_missing_visibility_hidden",
99628
- severity: "info",
99629
- 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.`,
99630
- elementId,
99631
- fixHint: 'Add class="clip" (with CSS: .clip { visibility: hidden; }) or style="opacity:0" if the element should start hidden.',
99632
- snippet: truncateSnippet(tag.raw)
99633
- });
99634
- }
99635
- }
99636
- for (const tag of tags) {
99637
- if (readAttr(tag.raw, "data-layer") && !readAttr(tag.raw, "data-track-index")) {
99638
- const elementId = readAttr(tag.raw, "id") || void 0;
99639
- pushFinding({
99640
- code: "deprecated_data_layer",
99641
- severity: "warning",
99642
- message: `<${tag.name}${elementId ? ` id="${elementId}"` : ""}> uses data-layer instead of data-track-index.`,
99643
- elementId,
99644
- fixHint: "Replace data-layer with data-track-index. The runtime reads data-track-index.",
99645
- snippet: truncateSnippet(tag.raw)
99646
- });
99647
- }
99648
- if (readAttr(tag.raw, "data-end") && !readAttr(tag.raw, "data-duration")) {
99649
- const elementId = readAttr(tag.raw, "id") || void 0;
99650
- pushFinding({
99651
- code: "deprecated_data_end",
99652
- severity: "warning",
99653
- message: `<${tag.name}${elementId ? ` id="${elementId}"` : ""}> uses data-end without data-duration. Use data-duration in source HTML.`,
99654
- elementId,
99655
- fixHint: "Replace data-end with data-duration. The compiler generates data-end from data-duration automatically.",
99656
- snippet: truncateSnippet(tag.raw)
99657
- });
99658
- }
99659
- }
99660
- for (const script of scripts) {
99661
- const templateLiteralSelectorPattern = /(?:querySelector|querySelectorAll)\s*\(\s*`[^`]*\$\{[^}]+\}[^`]*`\s*\)/g;
99662
- let tlMatch;
99663
- while ((tlMatch = templateLiteralSelectorPattern.exec(script.content)) !== null) {
99664
- pushFinding({
99665
- code: "template_literal_selector",
99666
- severity: "error",
99667
- message: "querySelector uses a template literal variable (e.g. `${compId}`). The HTML bundler's CSS parser crashes on these. Use a hardcoded string instead.",
99668
- file: filePath,
99669
- fixHint: "Replace the template literal variable with a hardcoded string. The bundler's CSS parser cannot handle interpolated variables in script content.",
99670
- snippet: truncateSnippet(tlMatch[0])
99671
- });
99672
- }
99673
- }
99674
- {
99675
- const cssTranslateSelectors = /* @__PURE__ */ new Map();
99676
- const cssScaleSelectors = /* @__PURE__ */ new Map();
99677
- for (const style of styles) {
99678
- for (const [, selector, body] of style.content.matchAll(
99679
- /([#.][a-zA-Z0-9_-]+)\s*\{([^}]+)\}/g
99680
- )) {
99681
- const tMatch = body?.match(/transform\s*:\s*([^;]+)/);
99682
- if (!tMatch || !tMatch[1]) continue;
99683
- const transformVal = tMatch[1].trim();
99684
- if (/translate/i.test(transformVal)) {
99685
- cssTranslateSelectors.set((selector ?? "").trim(), transformVal);
99686
- }
99687
- if (/scale/i.test(transformVal)) {
99688
- cssScaleSelectors.set((selector ?? "").trim(), transformVal);
99689
- }
99690
- }
99691
- }
99692
- if (cssTranslateSelectors.size > 0 || cssScaleSelectors.size > 0) {
99693
- for (const script of scripts) {
99694
- if (!/gsap\.timeline/.test(script.content)) continue;
99695
- const windows = extractGsapWindows(script.content);
99696
- const conflicts = /* @__PURE__ */ new Map();
99697
- for (const win of windows) {
99698
- if (win.method === "fromTo") continue;
99699
- const sel = win.targetSelector;
99700
- const cssKey = sel.startsWith("#") || sel.startsWith(".") ? sel : `#${sel}`;
99701
- const translateProps = win.properties.filter(
99702
- (p) => ["x", "y", "xPercent", "yPercent"].includes(p)
99703
- );
99704
- const scaleProps = win.properties.filter((p) => p === "scale");
99705
- const cssFromTranslate = translateProps.length > 0 ? cssTranslateSelectors.get(cssKey) : void 0;
99706
- const cssFromScale = scaleProps.length > 0 ? cssScaleSelectors.get(cssKey) : void 0;
99707
- if (!cssFromTranslate && !cssFromScale) continue;
99708
- const existing = conflicts.get(sel) ?? {
99709
- cssTransform: [cssFromTranslate, cssFromScale].filter(Boolean).join(" "),
99710
- props: /* @__PURE__ */ new Set(),
99711
- raw: win.raw
99712
- };
99713
- for (const p of [...translateProps, ...scaleProps]) existing.props.add(p);
99714
- conflicts.set(sel, existing);
99715
- }
99716
- for (const [sel, { cssTransform, props, raw: raw2 }] of conflicts) {
99717
- const propList = [...props].join("/");
99718
- pushFinding({
99719
- code: "gsap_css_transform_conflict",
99720
- severity: "warning",
99721
- 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.`,
99722
- selector: sel,
99723
- 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.`,
99724
- snippet: truncateSnippet(raw2)
99725
- });
99726
- }
99619
+ return findings;
99620
+ },
99621
+ // media_missing_id + media_missing_src + media_preload_none
99622
+ ({ tags }) => {
99623
+ const findings = [];
99624
+ for (const tag of tags) {
99625
+ if (tag.name !== "video" && tag.name !== "audio") continue;
99626
+ const hasDataStart = readAttr(tag.raw, "data-start");
99627
+ const hasId = readAttr(tag.raw, "id");
99628
+ const hasSrc = readAttr(tag.raw, "src");
99629
+ if (hasDataStart && !hasId) {
99630
+ findings.push({
99631
+ code: "media_missing_id",
99632
+ severity: "error",
99633
+ 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.`,
99634
+ fixHint: `Add a unique id attribute: <${tag.name} id="my-${tag.name}" ...>`,
99635
+ snippet: truncateSnippet(tag.raw)
99636
+ });
99727
99637
  }
99728
- }
99729
- }
99730
- for (const script of scripts) {
99731
- const content = script.content;
99732
- const hasExitTween = /\.to\s*\([^,]+,\s*\{[^}]*opacity\s*:\s*0/.test(content);
99733
- const hasHardKill = /\.set\s*\([^,]+,\s*\{[^}]*(?:visibility\s*:\s*["']hidden["']|opacity\s*:\s*0)/.test(content);
99734
- const hasCaptionLoop = /forEach|\.forEach\s*\(/.test(content) && /createElement|caption|group|cg-/.test(content);
99735
- if (hasCaptionLoop && hasExitTween && !hasHardKill) {
99736
- pushFinding({
99737
- code: "caption_exit_missing_hard_kill",
99738
- severity: "warning",
99739
- 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.",
99740
- fixHint: 'Add `tl.set(groupEl, { opacity: 0, visibility: "hidden" }, group.end)` after every exit tl.to animation as a deterministic kill.'
99741
- });
99742
- }
99743
- }
99744
- for (const style of styles) {
99745
- const content = style.content;
99746
- const captionBlocks = content.matchAll(
99747
- /(\.caption[-_]?(?:group|container|text|line|word)|#caption[-_]?container)\s*\{([^}]+)\}/gi
99748
- );
99749
- for (const [, selector, body] of captionBlocks) {
99750
- if (!body) continue;
99751
- const hasNowrap = /white-space\s*:\s*nowrap/i.test(body);
99752
- const hasMaxWidth = /max-width/i.test(body);
99753
- if (hasNowrap && !hasMaxWidth) {
99754
- pushFinding({
99755
- code: "caption_text_overflow_risk",
99756
- severity: "warning",
99757
- selector: (selector ?? "").trim(),
99758
- message: `Caption selector "${(selector ?? "").trim()}" has white-space: nowrap but no max-width. Long phrases will clip off-screen.`,
99759
- fixHint: "Add max-width: 1600px (landscape) or max-width: 900px (portrait) and overflow: hidden."
99638
+ if (hasDataStart && hasId && !hasSrc) {
99639
+ findings.push({
99640
+ code: "media_missing_src",
99641
+ severity: "error",
99642
+ message: `<${tag.name} id="${hasId}"> has data-start but no src attribute. The renderer cannot load this media.`,
99643
+ elementId: hasId,
99644
+ fixHint: `Add a src attribute to the <${tag.name}> element directly. If using <source> children, the renderer still requires src on the parent element.`,
99645
+ snippet: truncateSnippet(tag.raw)
99760
99646
  });
99761
99647
  }
99762
- }
99763
- }
99764
- for (const style of styles) {
99765
- const content = style.content;
99766
- const captionBlocks = content.matchAll(
99767
- /(\.caption[-_]?(?:group|container|text|line)|#caption[-_]?container)\s*\{([^}]+)\}/gi
99768
- );
99769
- for (const [, selector, body] of captionBlocks) {
99770
- if (!body) continue;
99771
- if (/position\s*:\s*relative/i.test(body)) {
99772
- pushFinding({
99773
- code: "caption_container_relative_position",
99648
+ if (readAttr(tag.raw, "preload") === "none") {
99649
+ findings.push({
99650
+ code: "media_preload_none",
99774
99651
  severity: "warning",
99775
- selector: (selector ?? "").trim(),
99776
- message: `Caption selector "${(selector ?? "").trim()}" uses position: relative which causes overflow and breaks caption stacking.`,
99777
- fixHint: "Use position: absolute for all caption elements."
99652
+ 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.`,
99653
+ elementId: hasId || void 0,
99654
+ fixHint: `Remove preload="none" or change to preload="auto". The framework manages media loading.`,
99655
+ snippet: truncateSnippet(tag.raw)
99778
99656
  });
99779
99657
  }
99780
99658
  }
99659
+ return findings;
99781
99660
  }
99782
- {
99783
- const externalScriptRe = /<script\b[^>]*\bsrc=["'](https?:\/\/[^"']+)["'][^>]*>/gi;
99784
- let match2;
99785
- const seen2 = /* @__PURE__ */ new Set();
99786
- while ((match2 = externalScriptRe.exec(source2)) !== null) {
99787
- const src = match2[1] ?? "";
99788
- if (seen2.has(src)) continue;
99789
- seen2.add(src);
99790
- pushFinding({
99791
- code: "external_script_dependency",
99792
- severity: "info",
99793
- 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.`,
99794
- 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.",
99795
- snippet: truncateSnippet(match2[0] ?? "")
99796
- });
99797
- }
99798
- }
99799
- const errorCount = findings.filter((finding) => finding.severity === "error").length;
99800
- const warningCount = findings.filter((finding) => finding.severity === "warning").length;
99801
- const infoCount = findings.filter((finding) => finding.severity === "info").length;
99802
- return {
99803
- ok: errorCount === 0,
99804
- errorCount,
99805
- warningCount,
99806
- infoCount,
99807
- findings
99808
- };
99809
- }
99810
- function extractOpenTags(source2) {
99811
- const tags = [];
99812
- let match2;
99813
- while ((match2 = TAG_PATTERN.exec(source2)) !== null) {
99814
- const raw2 = match2[0];
99815
- if (raw2.startsWith("</") || raw2.startsWith("<!")) {
99816
- continue;
99817
- }
99818
- tags.push({
99819
- raw: raw2,
99820
- name: (match2[1] || "").toLowerCase(),
99821
- attrs: match2[2] || "",
99822
- index: match2.index
99823
- });
99824
- }
99825
- return tags;
99826
- }
99827
- function extractBlocks(source2, pattern) {
99828
- const blocks = [];
99829
- let match2;
99830
- while ((match2 = pattern.exec(source2)) !== null) {
99831
- blocks.push({
99832
- attrs: match2[1] || "",
99833
- content: match2[2] || "",
99834
- raw: match2[0],
99835
- index: match2.index
99836
- });
99837
- }
99838
- return blocks;
99839
- }
99840
- function findRootTag(source2) {
99841
- const bodyMatch = source2.match(/<body\b[^>]*>([\s\S]*?)<\/body>/i);
99842
- const bodyContent = bodyMatch ? bodyMatch[1] ?? source2 : source2;
99843
- const bodyTags = extractOpenTags(bodyContent);
99844
- for (const tag of bodyTags) {
99845
- if (["script", "style", "meta", "link", "title"].includes(tag.name)) {
99846
- continue;
99847
- }
99848
- return tag;
99849
- }
99850
- return null;
99851
- }
99852
- function readAttr(tagSource, attr) {
99853
- if (!tagSource) {
99854
- return null;
99855
- }
99856
- const escaped = attr.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
99857
- const match2 = tagSource.match(new RegExp(`\\b${escaped}\\s*=\\s*["']([^"']+)["']`, "i"));
99858
- return match2?.[1] || null;
99859
- }
99860
- function collectCompositionIds(tags) {
99861
- const ids = /* @__PURE__ */ new Set();
99862
- for (const tag of tags) {
99863
- const compId = readAttr(tag.raw, "data-composition-id");
99864
- if (compId) {
99865
- ids.add(compId);
99866
- }
99867
- }
99868
- return ids;
99869
- }
99870
- function extractCompositionIdsFromCss(css) {
99871
- const ids = /* @__PURE__ */ new Set();
99872
- let match2;
99873
- while ((match2 = COMPOSITION_ID_IN_CSS_PATTERN.exec(css)) !== null) {
99874
- if (match2[1]) {
99875
- ids.add(match2[1]);
99876
- }
99877
- }
99878
- return [...ids];
99879
- }
99880
- function getInlineScriptSyntaxError(source2) {
99881
- if (!source2.trim()) {
99882
- return null;
99883
- }
99884
- try {
99885
- new Function(source2);
99886
- return null;
99887
- } catch (error) {
99888
- if (error instanceof Error) {
99889
- return error.message;
99890
- }
99891
- return String(error);
99892
- }
99893
- }
99894
- function isMediaTag(tagName19) {
99895
- return tagName19 === "video" || tagName19 === "audio" || tagName19 === "img";
99896
- }
99661
+ ];
99662
+
99663
+ // ../core/src/lint/rules/gsap.ts
99664
+ var META_GSAP_KEYS = /* @__PURE__ */ new Set(["duration", "ease", "repeat", "yoyo", "overwrite", "delay"]);
99897
99665
  function countClassUsage(tags) {
99898
99666
  const counts = /* @__PURE__ */ new Map();
99899
99667
  for (const tag of tags) {
99900
99668
  const classAttr = readAttr(tag.raw, "class");
99901
- if (!classAttr) {
99902
- continue;
99903
- }
99669
+ if (!classAttr) continue;
99904
99670
  for (const className of classAttr.split(/\s+/).filter(Boolean)) {
99905
99671
  counts.set(className, (counts.get(className) || 0) + 1);
99906
99672
  }
@@ -99912,13 +99678,9 @@ function readRegisteredTimelineCompositionId(script) {
99912
99678
  return match2?.[1] || null;
99913
99679
  }
99914
99680
  function extractGsapWindows(script) {
99915
- if (!/gsap\.timeline/.test(script)) {
99916
- return [];
99917
- }
99681
+ if (!/gsap\.timeline/.test(script)) return [];
99918
99682
  const parsed = parseGsapScript(script);
99919
- if (parsed.animations.length === 0) {
99920
- return [];
99921
- }
99683
+ if (parsed.animations.length === 0) return [];
99922
99684
  const windows = [];
99923
99685
  const timelineVar = parsed.timelineVar;
99924
99686
  const methodPattern = new RegExp(
@@ -99932,9 +99694,7 @@ function extractGsapWindows(script) {
99932
99694
  const meta = parseGsapWindowMeta(match2[1] ?? "", match2[2] ?? "");
99933
99695
  const animation = parsed.animations[index];
99934
99696
  index += 1;
99935
- if (!animation) {
99936
- continue;
99937
- }
99697
+ if (!animation) continue;
99938
99698
  windows.push({
99939
99699
  targetSelector: animation.targetSelector,
99940
99700
  position: animation.position,
@@ -99949,9 +99709,7 @@ function extractGsapWindows(script) {
99949
99709
  }
99950
99710
  function parseGsapWindowMeta(method, argsStr) {
99951
99711
  const selectorMatch = argsStr.match(/^\s*["']([^"']+)["']\s*,/);
99952
- if (!selectorMatch) {
99953
- return { effectiveDuration: 0, properties: [], overwriteAuto: false };
99954
- }
99712
+ if (!selectorMatch) return { effectiveDuration: 0, properties: [], overwriteAuto: false };
99955
99713
  const afterSelector = argsStr.slice(selectorMatch[0].length);
99956
99714
  let properties = {};
99957
99715
  let fromProperties = {};
@@ -99976,20 +99734,15 @@ function parseGsapWindowMeta(method, argsStr) {
99976
99734
  }
99977
99735
  const duration = numberValue(properties.duration) || 0;
99978
99736
  const repeat = numberValue(properties.repeat) || 0;
99979
- const yoyo = stringValue(properties.yoyo) === "true";
99980
99737
  const cycleCount = repeat > 0 ? repeat + 1 : 1;
99981
- const effectiveDuration = duration * cycleCount * (yoyo ? 1 : 1);
99738
+ const effectiveDuration = duration * cycleCount;
99982
99739
  const overwriteAuto = stringValue(properties.overwrite) === "auto";
99983
99740
  const propertyNames = /* @__PURE__ */ new Set();
99984
99741
  for (const key2 of Object.keys(fromProperties)) {
99985
- if (!META_GSAP_KEYS.has(key2)) {
99986
- propertyNames.add(key2);
99987
- }
99742
+ if (!META_GSAP_KEYS.has(key2)) propertyNames.add(key2);
99988
99743
  }
99989
99744
  for (const key2 of Object.keys(properties)) {
99990
- if (!META_GSAP_KEYS.has(key2)) {
99991
- propertyNames.add(key2);
99992
- }
99745
+ if (!META_GSAP_KEYS.has(key2)) propertyNames.add(key2);
99993
99746
  }
99994
99747
  return {
99995
99748
  effectiveDuration: method === "set" ? 0 : effectiveDuration,
@@ -100000,17 +99753,13 @@ function parseGsapWindowMeta(method, argsStr) {
100000
99753
  function parseLooseObjectLiteral(source2) {
100001
99754
  const result = {};
100002
99755
  const cleaned = source2.replace(/^\{|\}$/g, "").trim();
100003
- if (!cleaned) {
100004
- return result;
100005
- }
99756
+ if (!cleaned) return result;
100006
99757
  const propertyPattern = /(\w+)\s*:\s*("[^"]*"|'[^']*'|true|false|-?[\d.]+|[a-zA-Z_][\w.]*)/g;
100007
99758
  let match2;
100008
99759
  while ((match2 = propertyPattern.exec(cleaned)) !== null) {
100009
99760
  const key2 = match2[1];
100010
99761
  const rawValue = match2[2];
100011
- if (!key2 || rawValue == null) {
100012
- continue;
100013
- }
99762
+ if (!key2 || rawValue == null) continue;
100014
99763
  if (rawValue.startsWith('"') && rawValue.endsWith('"') || rawValue.startsWith("'") && rawValue.endsWith("'")) {
100015
99764
  result[key2] = rawValue.slice(1, -1);
100016
99765
  continue;
@@ -100021,26 +99770,19 @@ function parseLooseObjectLiteral(source2) {
100021
99770
  return result;
100022
99771
  }
100023
99772
  function findMatchingBrace2(source2, startIndex) {
100024
- if (startIndex < 0) {
100025
- return -1;
100026
- }
99773
+ if (startIndex < 0) return -1;
100027
99774
  let depth = 0;
100028
99775
  for (let i = startIndex; i < source2.length; i++) {
100029
- if (source2[i] === "{") {
100030
- depth += 1;
100031
- } else if (source2[i] === "}") {
99776
+ if (source2[i] === "{") depth += 1;
99777
+ else if (source2[i] === "}") {
100032
99778
  depth -= 1;
100033
- if (depth === 0) {
100034
- return i;
100035
- }
99779
+ if (depth === 0) return i;
100036
99780
  }
100037
99781
  }
100038
99782
  return -1;
100039
99783
  }
100040
99784
  function numberValue(value) {
100041
- if (typeof value === "number") {
100042
- return value;
100043
- }
99785
+ if (typeof value === "number") return value;
100044
99786
  if (typeof value === "string" && value.trim()) {
100045
99787
  const numeric = Number(value);
100046
99788
  return Number.isFinite(numeric) ? numeric : null;
@@ -100048,39 +99790,451 @@ function numberValue(value) {
100048
99790
  return null;
100049
99791
  }
100050
99792
  function stringValue(value) {
100051
- if (typeof value === "string") {
100052
- return value;
100053
- }
100054
- if (typeof value === "number") {
100055
- return String(value);
100056
- }
99793
+ if (typeof value === "string") return value;
99794
+ if (typeof value === "number") return String(value);
100057
99795
  return null;
100058
99796
  }
100059
99797
  function isSuspiciousGlobalSelector(selector) {
100060
- if (!selector) {
100061
- return false;
100062
- }
100063
- if (selector.includes("[data-composition-id=")) {
100064
- return false;
100065
- }
100066
- if (selector.startsWith("#")) {
100067
- return false;
100068
- }
99798
+ if (!selector) return false;
99799
+ if (selector.includes("[data-composition-id=")) return false;
99800
+ if (selector.startsWith("#")) return false;
100069
99801
  return selector.startsWith(".") || /^[a-z]/i.test(selector);
100070
99802
  }
100071
99803
  function getSingleClassSelector(selector) {
100072
99804
  const match2 = selector.trim().match(/^\.(?<name>[A-Za-z0-9_-]+)$/);
100073
99805
  return match2?.groups?.name || null;
100074
99806
  }
100075
- function truncateSnippet(value, maxLength = 220) {
100076
- const normalized = value.replace(/\s+/g, " ").trim();
100077
- if (!normalized) {
100078
- return void 0;
99807
+ var gsapRules = [
99808
+ // overlapping_gsap_tweens + gsap_animates_clip_element + unscoped_gsap_selector
99809
+ ({ tags, scripts, rootCompositionId }) => {
99810
+ const findings = [];
99811
+ const clipIds = /* @__PURE__ */ new Map();
99812
+ const clipClasses = /* @__PURE__ */ new Map();
99813
+ for (const tag of tags) {
99814
+ const classAttr = readAttr(tag.raw, "class") || "";
99815
+ const classes = classAttr.split(/\s+/).filter(Boolean);
99816
+ if (!classes.includes("clip")) continue;
99817
+ const id = readAttr(tag.raw, "id");
99818
+ const info = {
99819
+ tag: tag.name,
99820
+ id: id || "",
99821
+ classes: classAttr
99822
+ };
99823
+ if (id) clipIds.set(`#${id}`, info);
99824
+ for (const cls of classes) {
99825
+ if (cls !== "clip") clipClasses.set(`.${cls}`, info);
99826
+ }
99827
+ }
99828
+ const classUsage = countClassUsage(tags);
99829
+ for (const script of scripts) {
99830
+ const localTimelineCompId = readRegisteredTimelineCompositionId(script.content);
99831
+ const gsapWindows = extractGsapWindows(script.content);
99832
+ for (let i = 0; i < gsapWindows.length; i++) {
99833
+ const left2 = gsapWindows[i];
99834
+ if (!left2) continue;
99835
+ if (left2.end <= left2.position) continue;
99836
+ for (let j = i + 1; j < gsapWindows.length; j++) {
99837
+ const right2 = gsapWindows[j];
99838
+ if (!right2) continue;
99839
+ if (right2.end <= right2.position) continue;
99840
+ if (left2.targetSelector !== right2.targetSelector) continue;
99841
+ const overlapStart = Math.max(left2.position, right2.position);
99842
+ const overlapEnd = Math.min(left2.end, right2.end);
99843
+ if (overlapEnd <= overlapStart) continue;
99844
+ if (left2.overwriteAuto || right2.overwriteAuto) continue;
99845
+ const sharedProperties = left2.properties.filter(
99846
+ (prop2) => right2.properties.includes(prop2)
99847
+ );
99848
+ if (sharedProperties.length === 0) continue;
99849
+ findings.push({
99850
+ code: "overlapping_gsap_tweens",
99851
+ severity: "warning",
99852
+ message: `GSAP tweens overlap on "${left2.targetSelector}" for ${sharedProperties.join(", ")} between ${overlapStart.toFixed(2)}s and ${overlapEnd.toFixed(2)}s.`,
99853
+ selector: left2.targetSelector,
99854
+ fixHint: 'Shorten the earlier tween, move the later tween, or add `overwrite: "auto"`.',
99855
+ snippet: truncateSnippet(`${left2.raw}
99856
+ ${right2.raw}`)
99857
+ });
99858
+ }
99859
+ }
99860
+ for (const win of gsapWindows) {
99861
+ const sel = win.targetSelector;
99862
+ const clipInfo = clipIds.get(sel) || clipClasses.get(sel);
99863
+ if (!clipInfo) continue;
99864
+ const elDesc = `<${clipInfo.tag}${clipInfo.id ? ` id="${clipInfo.id}"` : ""} class="${clipInfo.classes}">`;
99865
+ findings.push({
99866
+ code: "gsap_animates_clip_element",
99867
+ severity: "error",
99868
+ message: `GSAP animation targets a clip element. Selector "${sel}" resolves to element ${elDesc}. The framework manages clip visibility \u2014 animate an inner wrapper instead.`,
99869
+ selector: sel,
99870
+ elementId: clipInfo.id || void 0,
99871
+ fixHint: "Wrap content in a child <div> and target that with GSAP.",
99872
+ snippet: truncateSnippet(win.raw)
99873
+ });
99874
+ }
99875
+ if (!localTimelineCompId || localTimelineCompId === rootCompositionId) continue;
99876
+ for (const win of gsapWindows) {
99877
+ if (!isSuspiciousGlobalSelector(win.targetSelector)) continue;
99878
+ const className = getSingleClassSelector(win.targetSelector);
99879
+ if (className && (classUsage.get(className) || 0) < 2) continue;
99880
+ findings.push({
99881
+ code: "unscoped_gsap_selector",
99882
+ severity: "warning",
99883
+ message: `Timeline "${localTimelineCompId}" uses unscoped selector "${win.targetSelector}" that will target elements in ALL compositions when bundled, causing data loss (opacity, transforms, etc.).`,
99884
+ selector: win.targetSelector,
99885
+ fixHint: `Scope the selector: \`[data-composition-id="${localTimelineCompId}"] ${win.targetSelector}\` or use a unique id.`,
99886
+ snippet: truncateSnippet(win.raw)
99887
+ });
99888
+ }
99889
+ }
99890
+ return findings;
99891
+ },
99892
+ // gsap_css_transform_conflict
99893
+ ({ styles, scripts }) => {
99894
+ const findings = [];
99895
+ const cssTranslateSelectors = /* @__PURE__ */ new Map();
99896
+ const cssScaleSelectors = /* @__PURE__ */ new Map();
99897
+ for (const style of styles) {
99898
+ for (const [, selector, body] of style.content.matchAll(
99899
+ /([#.][a-zA-Z0-9_-]+)\s*\{([^}]+)\}/g
99900
+ )) {
99901
+ const tMatch = body?.match(/transform\s*:\s*([^;]+)/);
99902
+ if (!tMatch || !tMatch[1]) continue;
99903
+ const transformVal = tMatch[1].trim();
99904
+ if (/translate/i.test(transformVal))
99905
+ cssTranslateSelectors.set((selector ?? "").trim(), transformVal);
99906
+ if (/scale/i.test(transformVal))
99907
+ cssScaleSelectors.set((selector ?? "").trim(), transformVal);
99908
+ }
99909
+ }
99910
+ if (cssTranslateSelectors.size === 0 && cssScaleSelectors.size === 0) return findings;
99911
+ for (const script of scripts) {
99912
+ if (!/gsap\.timeline/.test(script.content)) continue;
99913
+ const windows = extractGsapWindows(script.content);
99914
+ const conflicts = /* @__PURE__ */ new Map();
99915
+ for (const win of windows) {
99916
+ if (win.method === "fromTo") continue;
99917
+ const sel = win.targetSelector;
99918
+ const cssKey = sel.startsWith("#") || sel.startsWith(".") ? sel : `#${sel}`;
99919
+ const translateProps = win.properties.filter(
99920
+ (p) => ["x", "y", "xPercent", "yPercent"].includes(p)
99921
+ );
99922
+ const scaleProps = win.properties.filter((p) => p === "scale");
99923
+ const cssFromTranslate = translateProps.length > 0 ? cssTranslateSelectors.get(cssKey) : void 0;
99924
+ const cssFromScale = scaleProps.length > 0 ? cssScaleSelectors.get(cssKey) : void 0;
99925
+ if (!cssFromTranslate && !cssFromScale) continue;
99926
+ const existing = conflicts.get(sel) ?? {
99927
+ cssTransform: [cssFromTranslate, cssFromScale].filter(Boolean).join(" "),
99928
+ props: /* @__PURE__ */ new Set(),
99929
+ raw: win.raw
99930
+ };
99931
+ for (const p of [...translateProps, ...scaleProps]) existing.props.add(p);
99932
+ conflicts.set(sel, existing);
99933
+ }
99934
+ for (const [sel, { cssTransform, props, raw: raw2 }] of conflicts) {
99935
+ const propList = [...props].join("/");
99936
+ findings.push({
99937
+ code: "gsap_css_transform_conflict",
99938
+ severity: "warning",
99939
+ 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.`,
99940
+ selector: sel,
99941
+ 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.`,
99942
+ snippet: truncateSnippet(raw2)
99943
+ });
99944
+ }
99945
+ }
99946
+ return findings;
99947
+ },
99948
+ // missing_gsap_script
99949
+ ({ scripts }) => {
99950
+ const allScriptTexts = scripts.filter((s) => !/\bsrc\s*=/.test(s.attrs)).map((s) => s.content);
99951
+ const allScriptSrcs = scripts.map((s) => readAttr(`<script ${s.attrs}>`, "src") || "").filter(Boolean);
99952
+ const usesGsap = allScriptTexts.some(
99953
+ (t) => /gsap\.(to|from|fromTo|timeline|set|registerPlugin)\b/.test(t)
99954
+ );
99955
+ const hasGsapScript = allScriptSrcs.some((src) => /gsap/i.test(src));
99956
+ if (!usesGsap || hasGsapScript) return [];
99957
+ return [
99958
+ {
99959
+ code: "missing_gsap_script",
99960
+ severity: "error",
99961
+ message: "Composition uses GSAP but no GSAP script is loaded. The animation will not run.",
99962
+ fixHint: 'Add <script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js"></script> before your animation script.'
99963
+ }
99964
+ ];
100079
99965
  }
100080
- if (normalized.length <= maxLength) {
100081
- return normalized;
99966
+ ];
99967
+
99968
+ // ../core/src/lint/rules/captions.ts
99969
+ var captionRules = [
99970
+ // caption_exit_missing_hard_kill
99971
+ ({ scripts }) => {
99972
+ const findings = [];
99973
+ for (const script of scripts) {
99974
+ const content = script.content;
99975
+ const hasExitTween = /\.to\s*\([^,]+,\s*\{[^}]*opacity\s*:\s*0/.test(content);
99976
+ const hasHardKill = /\.set\s*\([^,]+,\s*\{[^}]*(?:visibility\s*:\s*["']hidden["']|opacity\s*:\s*0)/.test(
99977
+ content
99978
+ );
99979
+ const hasCaptionLoop = /forEach|\.forEach\s*\(/.test(content) && /createElement|caption|group|cg-/.test(content);
99980
+ if (hasCaptionLoop && hasExitTween && !hasHardKill) {
99981
+ findings.push({
99982
+ code: "caption_exit_missing_hard_kill",
99983
+ severity: "warning",
99984
+ 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.",
99985
+ fixHint: 'Add `tl.set(groupEl, { opacity: 0, visibility: "hidden" }, group.end)` after every exit tl.to animation as a deterministic kill.'
99986
+ });
99987
+ }
99988
+ }
99989
+ return findings;
99990
+ },
99991
+ // caption_text_overflow_risk
99992
+ ({ styles }) => {
99993
+ const findings = [];
99994
+ for (const style of styles) {
99995
+ const captionBlocks = style.content.matchAll(
99996
+ /(\.caption[-_]?(?:group|container|text|line|word)|#caption[-_]?container)\s*\{([^}]+)\}/gi
99997
+ );
99998
+ for (const [, selector, body] of captionBlocks) {
99999
+ if (!body) continue;
100000
+ const hasNowrap = /white-space\s*:\s*nowrap/i.test(body);
100001
+ const hasMaxWidth = /max-width/i.test(body);
100002
+ if (hasNowrap && !hasMaxWidth) {
100003
+ findings.push({
100004
+ code: "caption_text_overflow_risk",
100005
+ severity: "warning",
100006
+ selector: (selector ?? "").trim(),
100007
+ message: `Caption selector "${(selector ?? "").trim()}" has white-space: nowrap but no max-width. Long phrases will clip off-screen.`,
100008
+ fixHint: "Add max-width: 1600px (landscape) or max-width: 900px (portrait) and overflow: hidden."
100009
+ });
100010
+ }
100011
+ }
100012
+ }
100013
+ return findings;
100014
+ },
100015
+ // caption_container_relative_position
100016
+ ({ styles }) => {
100017
+ const findings = [];
100018
+ for (const style of styles) {
100019
+ const captionBlocks = style.content.matchAll(
100020
+ /(\.caption[-_]?(?:group|container|text|line)|#caption[-_]?container)\s*\{([^}]+)\}/gi
100021
+ );
100022
+ for (const [, selector, body] of captionBlocks) {
100023
+ if (!body) continue;
100024
+ if (/position\s*:\s*relative/i.test(body)) {
100025
+ findings.push({
100026
+ code: "caption_container_relative_position",
100027
+ severity: "warning",
100028
+ selector: (selector ?? "").trim(),
100029
+ message: `Caption selector "${(selector ?? "").trim()}" uses position: relative which causes overflow and breaks caption stacking.`,
100030
+ fixHint: "Use position: absolute for all caption elements."
100031
+ });
100032
+ }
100033
+ }
100034
+ }
100035
+ return findings;
100036
+ }
100037
+ ];
100038
+
100039
+ // ../core/src/lint/rules/composition.ts
100040
+ var compositionRules = [
100041
+ // timed_element_missing_visibility_hidden
100042
+ ({ tags }) => {
100043
+ const findings = [];
100044
+ for (const tag of tags) {
100045
+ if (tag.name === "audio" || tag.name === "script" || tag.name === "style") continue;
100046
+ if (!readAttr(tag.raw, "data-start")) continue;
100047
+ if (readAttr(tag.raw, "data-composition-id")) continue;
100048
+ if (readAttr(tag.raw, "data-composition-src")) continue;
100049
+ const classAttr = readAttr(tag.raw, "class") || "";
100050
+ const styleAttr = readAttr(tag.raw, "style") || "";
100051
+ const hasClip = classAttr.split(/\s+/).includes("clip");
100052
+ const hasHiddenStyle = /visibility\s*:\s*hidden/i.test(styleAttr) || /opacity\s*:\s*0/i.test(styleAttr);
100053
+ if (!hasClip && !hasHiddenStyle) {
100054
+ const elementId = readAttr(tag.raw, "id") || void 0;
100055
+ findings.push({
100056
+ code: "timed_element_missing_visibility_hidden",
100057
+ severity: "info",
100058
+ 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.`,
100059
+ elementId,
100060
+ fixHint: 'Add class="clip" (with CSS: .clip { visibility: hidden; }) or style="opacity:0" if the element should start hidden.',
100061
+ snippet: truncateSnippet(tag.raw)
100062
+ });
100063
+ }
100064
+ }
100065
+ return findings;
100066
+ },
100067
+ // deprecated_data_layer + deprecated_data_end
100068
+ ({ tags }) => {
100069
+ const findings = [];
100070
+ for (const tag of tags) {
100071
+ if (readAttr(tag.raw, "data-layer") && !readAttr(tag.raw, "data-track-index")) {
100072
+ const elementId = readAttr(tag.raw, "id") || void 0;
100073
+ findings.push({
100074
+ code: "deprecated_data_layer",
100075
+ severity: "warning",
100076
+ message: `<${tag.name}${elementId ? ` id="${elementId}"` : ""}> uses data-layer instead of data-track-index.`,
100077
+ elementId,
100078
+ fixHint: "Replace data-layer with data-track-index. The runtime reads data-track-index.",
100079
+ snippet: truncateSnippet(tag.raw)
100080
+ });
100081
+ }
100082
+ if (readAttr(tag.raw, "data-end") && !readAttr(tag.raw, "data-duration")) {
100083
+ const elementId = readAttr(tag.raw, "id") || void 0;
100084
+ findings.push({
100085
+ code: "deprecated_data_end",
100086
+ severity: "warning",
100087
+ message: `<${tag.name}${elementId ? ` id="${elementId}"` : ""}> uses data-end without data-duration. Use data-duration in source HTML.`,
100088
+ elementId,
100089
+ fixHint: "Replace data-end with data-duration. The compiler generates data-end from data-duration automatically.",
100090
+ snippet: truncateSnippet(tag.raw)
100091
+ });
100092
+ }
100093
+ }
100094
+ return findings;
100095
+ },
100096
+ // template_literal_selector
100097
+ ({ scripts }) => {
100098
+ const findings = [];
100099
+ for (const script of scripts) {
100100
+ const templateLiteralSelectorPattern = /(?:querySelector|querySelectorAll)\s*\(\s*`[^`]*\$\{[^}]+\}[^`]*`\s*\)/g;
100101
+ let tlMatch;
100102
+ while ((tlMatch = templateLiteralSelectorPattern.exec(script.content)) !== null) {
100103
+ findings.push({
100104
+ code: "template_literal_selector",
100105
+ severity: "error",
100106
+ message: "querySelector uses a template literal variable (e.g. `${compId}`). The HTML bundler's CSS parser crashes on these. Use a hardcoded string instead.",
100107
+ fixHint: "Replace the template literal variable with a hardcoded string. The bundler's CSS parser cannot handle interpolated variables in script content.",
100108
+ snippet: truncateSnippet(tlMatch[0])
100109
+ });
100110
+ }
100111
+ }
100112
+ return findings;
100113
+ },
100114
+ // external_script_dependency
100115
+ ({ source: source2 }) => {
100116
+ const findings = [];
100117
+ const externalScriptRe = /<script\b[^>]*\bsrc=["'](https?:\/\/[^"']+)["'][^>]*>/gi;
100118
+ let match2;
100119
+ const seen = /* @__PURE__ */ new Set();
100120
+ while ((match2 = externalScriptRe.exec(source2)) !== null) {
100121
+ const src = match2[1] ?? "";
100122
+ if (seen.has(src)) continue;
100123
+ seen.add(src);
100124
+ findings.push({
100125
+ code: "external_script_dependency",
100126
+ severity: "info",
100127
+ 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.`,
100128
+ 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.",
100129
+ snippet: truncateSnippet(match2[0] ?? "")
100130
+ });
100131
+ }
100132
+ return findings;
100133
+ }
100134
+ ];
100135
+
100136
+ // ../core/src/lint/rules/adapters.ts
100137
+ var adapterRules = [
100138
+ // missing_lottie_script
100139
+ ({ tags, scripts }) => {
100140
+ const allScriptTexts = scripts.filter((s) => !/\bsrc\s*=/.test(s.attrs)).map((s) => s.content);
100141
+ const allScriptSrcs = scripts.map((s) => readAttr(`<script ${s.attrs}>`, "src") || "").filter(Boolean);
100142
+ const hasLottieAttr = tags.some((t) => readAttr(t.raw, "data-lottie-src") !== null);
100143
+ const usesLottieApi = allScriptTexts.some(
100144
+ (t) => /lottie\.(loadAnimation|setSpeed|play|stop|destroy)\b/.test(t)
100145
+ );
100146
+ const hasLottieScript = allScriptSrcs.some((src) => /lottie/i.test(src));
100147
+ if (!(hasLottieAttr || usesLottieApi) || hasLottieScript) return [];
100148
+ return [
100149
+ {
100150
+ code: "missing_lottie_script",
100151
+ severity: "error",
100152
+ message: "Composition uses Lottie but no Lottie script is loaded. The animation will not render.",
100153
+ fixHint: 'Add <script src="https://cdn.jsdelivr.net/npm/lottie-web@5/build/player/lottie.min.js"></script> before your Lottie code.'
100154
+ }
100155
+ ];
100156
+ },
100157
+ // missing_three_script
100158
+ ({ scripts }) => {
100159
+ const allScriptTexts = scripts.filter((s) => !/\bsrc\s*=/.test(s.attrs)).map((s) => s.content);
100160
+ const allScriptSrcs = scripts.map((s) => readAttr(`<script ${s.attrs}>`, "src") || "").filter(Boolean);
100161
+ const usesThree = allScriptTexts.some((t) => /\bTHREE\./.test(t));
100162
+ const hasThreeScript = allScriptSrcs.some((src) => /three/i.test(src));
100163
+ if (!usesThree || hasThreeScript) return [];
100164
+ return [
100165
+ {
100166
+ code: "missing_three_script",
100167
+ severity: "error",
100168
+ message: "Composition uses Three.js but no Three.js script is loaded. The 3D scene will not render.",
100169
+ fixHint: 'Add <script src="https://cdn.jsdelivr.net/npm/three@0.160/build/three.min.js"></script> before your Three.js code.'
100170
+ }
100171
+ ];
100172
+ }
100173
+ ];
100174
+
100175
+ // ../core/src/lint/hyperframeLinter.ts
100176
+ var ALL_RULES = [
100177
+ ...coreRules,
100178
+ ...mediaRules,
100179
+ ...gsapRules,
100180
+ ...captionRules,
100181
+ ...compositionRules,
100182
+ ...adapterRules
100183
+ ];
100184
+ function lintHyperframeHtml(html, options = {}) {
100185
+ const ctx = buildLintContext(html, options);
100186
+ const findings = [];
100187
+ const seen = /* @__PURE__ */ new Set();
100188
+ for (const rule of ALL_RULES) {
100189
+ for (const finding of rule(ctx)) {
100190
+ const dedupeKey = [
100191
+ finding.code,
100192
+ finding.severity,
100193
+ finding.selector || "",
100194
+ finding.elementId || "",
100195
+ finding.message
100196
+ ].join("|");
100197
+ if (seen.has(dedupeKey)) continue;
100198
+ seen.add(dedupeKey);
100199
+ findings.push(options.filePath ? { ...finding, file: options.filePath } : finding);
100200
+ }
100201
+ }
100202
+ const errorCount = findings.filter((f) => f.severity === "error").length;
100203
+ const warningCount = findings.filter((f) => f.severity === "warning").length;
100204
+ const infoCount = findings.filter((f) => f.severity === "info").length;
100205
+ return {
100206
+ ok: errorCount === 0,
100207
+ errorCount,
100208
+ warningCount,
100209
+ infoCount,
100210
+ findings
100211
+ };
100212
+ }
100213
+
100214
+ // ../core/src/compiler/rewriteSubCompPaths.ts
100215
+ import { join as join4, resolve as resolve6, dirname as dirname4 } from "path";
100216
+ var PATH_ATTRS = ["src", "href"];
100217
+ function isAbsoluteOrSpecial(val) {
100218
+ return !val || val.startsWith("http://") || val.startsWith("https://") || val.startsWith("//") || val.startsWith("data:") || val.startsWith("#");
100219
+ }
100220
+ function needsRewrite(val) {
100221
+ return val.startsWith("../") || val === "..";
100222
+ }
100223
+ function rewriteAssetPaths(elements, compSrcPath, getAttr2, setAttr) {
100224
+ const compDir = dirname4(compSrcPath);
100225
+ if (!compDir || compDir === ".") return;
100226
+ for (const el of elements) {
100227
+ for (const attr of PATH_ATTRS) {
100228
+ const val = (getAttr2(el, attr) || "").trim();
100229
+ if (isAbsoluteOrSpecial(val)) continue;
100230
+ if (!needsRewrite(val)) continue;
100231
+ const rewritten = join4(compDir, val);
100232
+ const normalized = resolve6("/", rewritten).slice(1);
100233
+ if (normalized !== val) {
100234
+ setAttr(el, attr, normalized);
100235
+ }
100236
+ }
100082
100237
  }
100083
- return `${normalized.slice(0, maxLength - 3)}...`;
100084
100238
  }
100085
100239
 
100086
100240
  // ../core/src/inline-scripts/hyperframesRuntime.engine.ts
@@ -100448,9 +100602,9 @@ async function initializeSession(session) {
100448
100602
  }
100449
100603
  async function captureFrameErrorDiagnostics(session, frameIndex, time, error) {
100450
100604
  try {
100451
- const diagnosticsDir = join4(session.outputDir, "diagnostics");
100605
+ const diagnosticsDir = join5(session.outputDir, "diagnostics");
100452
100606
  if (!existsSync4(diagnosticsDir)) mkdirSync(diagnosticsDir, { recursive: true });
100453
- const base = join4(diagnosticsDir, `frame-error-${frameIndex}`);
100607
+ const base = join5(diagnosticsDir, `frame-error-${frameIndex}`);
100454
100608
  await session.page.screenshot({ path: `${base}.png`, type: "png", fullPage: true });
100455
100609
  const html = await session.page.content();
100456
100610
  writeFileSync(`${base}.html`, html, "utf-8");
@@ -100548,7 +100702,7 @@ async function captureFrame(session, frameIndex, time) {
100548
100702
  );
100549
100703
  const ext = options.format === "png" ? "png" : "jpg";
100550
100704
  const frameName = `frame_${String(frameIndex).padStart(6, "0")}.${ext}`;
100551
- const framePath = join4(outputDir, frameName);
100705
+ const framePath = join5(outputDir, frameName);
100552
100706
  writeFileSync(framePath, buffer);
100553
100707
  return { frameIndex, time: quantizedTime, path: framePath, captureTimeMs };
100554
100708
  }
@@ -100598,12 +100752,12 @@ function getCapturePerfSummary(session) {
100598
100752
  // ../engine/src/services/chunkEncoder.ts
100599
100753
  import { spawn as spawn5 } from "child_process";
100600
100754
  import { copyFileSync, existsSync as existsSync5, mkdirSync as mkdirSync2, readdirSync as readdirSync3, statSync as statSync3, writeFileSync as writeFileSync2 } from "fs";
100601
- import { join as join5, dirname as dirname4 } from "path";
100755
+ import { join as join6, dirname as dirname5 } from "path";
100602
100756
 
100603
100757
  // ../engine/src/utils/gpuEncoder.ts
100604
100758
  import { spawn as spawn3 } from "child_process";
100605
100759
  async function detectGpuEncoder() {
100606
- return new Promise((resolve12) => {
100760
+ return new Promise((resolve13) => {
100607
100761
  const ffmpeg = spawn3("ffmpeg", ["-encoders"], {
100608
100762
  stdio: ["pipe", "pipe", "pipe"]
100609
100763
  });
@@ -100612,13 +100766,13 @@ async function detectGpuEncoder() {
100612
100766
  stdout += data.toString();
100613
100767
  });
100614
100768
  ffmpeg.on("close", () => {
100615
- if (stdout.includes("h264_nvenc")) resolve12("nvenc");
100616
- else if (stdout.includes("h264_videotoolbox")) resolve12("videotoolbox");
100617
- else if (stdout.includes("h264_vaapi")) resolve12("vaapi");
100618
- else if (stdout.includes("h264_qsv")) resolve12("qsv");
100619
- else resolve12(null);
100769
+ if (stdout.includes("h264_nvenc")) resolve13("nvenc");
100770
+ else if (stdout.includes("h264_videotoolbox")) resolve13("videotoolbox");
100771
+ else if (stdout.includes("h264_vaapi")) resolve13("vaapi");
100772
+ else if (stdout.includes("h264_qsv")) resolve13("qsv");
100773
+ else resolve13(null);
100620
100774
  });
100621
- ffmpeg.on("error", () => resolve12(null));
100775
+ ffmpeg.on("error", () => resolve13(null));
100622
100776
  });
100623
100777
  }
100624
100778
  var cachedGpuEncoder = void 0;
@@ -100652,7 +100806,7 @@ async function runFfmpeg(args, opts) {
100652
100806
  const signal = opts?.signal;
100653
100807
  const timeout2 = opts?.timeout ?? DEFAULT_TIMEOUT2;
100654
100808
  const onStderr = opts?.onStderr;
100655
- return new Promise((resolve12) => {
100809
+ return new Promise((resolve13) => {
100656
100810
  const ffmpeg = spawn4("ffmpeg", args);
100657
100811
  let stderr = "";
100658
100812
  const onAbort = () => {
@@ -100678,7 +100832,7 @@ async function runFfmpeg(args, opts) {
100678
100832
  ffmpeg.on("close", (code) => {
100679
100833
  clearTimeout(timer2);
100680
100834
  if (signal) signal.removeEventListener("abort", onAbort);
100681
- resolve12({
100835
+ resolve13({
100682
100836
  success: !signal?.aborted && code === 0,
100683
100837
  exitCode: code,
100684
100838
  stderr,
@@ -100688,7 +100842,7 @@ async function runFfmpeg(args, opts) {
100688
100842
  ffmpeg.on("error", (err) => {
100689
100843
  clearTimeout(timer2);
100690
100844
  if (signal) signal.removeEventListener("abort", onAbort);
100691
- resolve12({
100845
+ resolve13({
100692
100846
  success: false,
100693
100847
  exitCode: null,
100694
100848
  stderr: err.message,
@@ -100784,7 +100938,7 @@ function buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder = null) {
100784
100938
  }
100785
100939
  async function encodeFramesFromDir(framesDir, framePattern, outputPath, options, signal, config2) {
100786
100940
  const startTime = Date.now();
100787
- const outputDir = dirname4(outputPath);
100941
+ const outputDir = dirname5(outputPath);
100788
100942
  if (!existsSync5(outputDir)) mkdirSync2(outputDir, { recursive: true });
100789
100943
  const files = readdirSync3(framesDir).filter((f) => f.match(/\.(jpg|jpeg|png)$/i));
100790
100944
  const frameCount = files.length;
@@ -100802,10 +100956,10 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
100802
100956
  if (options.useGpu) {
100803
100957
  gpuEncoder = await getCachedGpuEncoder();
100804
100958
  }
100805
- const inputPath = join5(framesDir, framePattern);
100959
+ const inputPath = join6(framesDir, framePattern);
100806
100960
  const inputArgs = ["-framerate", String(options.fps), "-i", inputPath];
100807
100961
  const args = buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder);
100808
- return new Promise((resolve12) => {
100962
+ return new Promise((resolve13) => {
100809
100963
  const ffmpeg = spawn5("ffmpeg", args);
100810
100964
  let stderr = "";
100811
100965
  const onAbort = () => {
@@ -100830,7 +100984,7 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
100830
100984
  if (signal) signal.removeEventListener("abort", onAbort);
100831
100985
  const durationMs = Date.now() - startTime;
100832
100986
  if (signal?.aborted) {
100833
- resolve12({
100987
+ resolve13({
100834
100988
  success: false,
100835
100989
  outputPath,
100836
100990
  durationMs,
@@ -100841,7 +100995,7 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
100841
100995
  return;
100842
100996
  }
100843
100997
  if (code !== 0) {
100844
- resolve12({
100998
+ resolve13({
100845
100999
  success: false,
100846
101000
  outputPath,
100847
101001
  durationMs,
@@ -100852,12 +101006,12 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
100852
101006
  return;
100853
101007
  }
100854
101008
  const fileSize = existsSync5(outputPath) ? statSync3(outputPath).size : 0;
100855
- resolve12({ success: true, outputPath, durationMs, framesEncoded: frameCount, fileSize });
101009
+ resolve13({ success: true, outputPath, durationMs, framesEncoded: frameCount, fileSize });
100856
101010
  });
100857
101011
  ffmpeg.on("error", (err) => {
100858
101012
  clearTimeout(timer2);
100859
101013
  if (signal) signal.removeEventListener("abort", onAbort);
100860
- resolve12({
101014
+ resolve13({
100861
101015
  success: false,
100862
101016
  outputPath,
100863
101017
  durationMs: Date.now() - startTime,
@@ -100883,7 +101037,7 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
100883
101037
  }
100884
101038
  const chunkSize = Math.max(30, Math.floor(chunkSizeFrames));
100885
101039
  const chunkCount = Math.ceil(files.length / chunkSize);
100886
- const chunkDir = join5(dirname4(outputPath), "chunk-encode");
101040
+ const chunkDir = join6(dirname5(outputPath), "chunk-encode");
100887
101041
  if (!existsSync5(chunkDir)) mkdirSync2(chunkDir, { recursive: true });
100888
101042
  const chunkPaths = [];
100889
101043
  for (let i = 0; i < chunkCount; i++) {
@@ -100900,8 +101054,8 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
100900
101054
  const startNumber = i * chunkSize;
100901
101055
  const framesInChunk = Math.min(chunkSize, files.length - startNumber);
100902
101056
  const ext = outputPath.endsWith(".webm") ? ".webm" : ".mp4";
100903
- const chunkPath = join5(chunkDir, `chunk_${String(i).padStart(4, "0")}${ext}`);
100904
- const inputPath = join5(framesDir, framePattern);
101057
+ const chunkPath = join6(chunkDir, `chunk_${String(i).padStart(4, "0")}${ext}`);
101058
+ const inputPath = join6(framesDir, framePattern);
100905
101059
  const inputArgs = [
100906
101060
  "-framerate",
100907
101061
  String(options.fps),
@@ -100915,18 +101069,18 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
100915
101069
  let gpuEncoder = null;
100916
101070
  if (options.useGpu) gpuEncoder = await getCachedGpuEncoder();
100917
101071
  const args = buildEncoderArgs(options, inputArgs, chunkPath, gpuEncoder);
100918
- const chunkResult = await new Promise((resolve12) => {
101072
+ const chunkResult = await new Promise((resolve13) => {
100919
101073
  const ffmpeg = spawn5("ffmpeg", args);
100920
101074
  let stderr = "";
100921
101075
  ffmpeg.stderr.on("data", (d) => {
100922
101076
  stderr += d.toString();
100923
101077
  });
100924
101078
  ffmpeg.on("close", (code) => {
100925
- if (code === 0) resolve12({ success: true });
100926
- else resolve12({ success: false, error: `Chunk ${i} encode failed: ${stderr.slice(-400)}` });
101079
+ if (code === 0) resolve13({ success: true });
101080
+ else resolve13({ success: false, error: `Chunk ${i} encode failed: ${stderr.slice(-400)}` });
100927
101081
  });
100928
101082
  ffmpeg.on("error", (err) => {
100929
- resolve12({ success: false, error: `Chunk ${i} encode error: ${err.message}` });
101083
+ resolve13({ success: false, error: `Chunk ${i} encode error: ${err.message}` });
100930
101084
  });
100931
101085
  });
100932
101086
  if (!chunkResult.success) {
@@ -100941,7 +101095,7 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
100941
101095
  }
100942
101096
  chunkPaths.push(chunkPath);
100943
101097
  }
100944
- const concatListPath = join5(chunkDir, "concat-list.txt");
101098
+ const concatListPath = join6(chunkDir, "concat-list.txt");
100945
101099
  const concatInput = chunkPaths.map((path12) => `file '${path12.replace(/'/g, "'\\''")}'`).join("\n");
100946
101100
  writeFileSync2(concatListPath, concatInput, "utf-8");
100947
101101
  const concatArgs = [
@@ -100956,18 +101110,18 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
100956
101110
  "-y",
100957
101111
  outputPath
100958
101112
  ];
100959
- const concatResult = await new Promise((resolve12) => {
101113
+ const concatResult = await new Promise((resolve13) => {
100960
101114
  const ffmpeg = spawn5("ffmpeg", concatArgs);
100961
101115
  let stderr = "";
100962
101116
  ffmpeg.stderr.on("data", (d) => {
100963
101117
  stderr += d.toString();
100964
101118
  });
100965
101119
  ffmpeg.on("close", (code) => {
100966
- if (code === 0) resolve12({ success: true });
100967
- else resolve12({ success: false, error: `Chunk concat failed: ${stderr.slice(-400)}` });
101120
+ if (code === 0) resolve13({ success: true });
101121
+ else resolve13({ success: false, error: `Chunk concat failed: ${stderr.slice(-400)}` });
100968
101122
  });
100969
101123
  ffmpeg.on("error", (err) => {
100970
- resolve12({ success: false, error: `Chunk concat error: ${err.message}` });
101124
+ resolve13({ success: false, error: `Chunk concat error: ${err.message}` });
100971
101125
  });
100972
101126
  });
100973
101127
  if (!concatResult.success) {
@@ -100990,7 +101144,7 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
100990
101144
  };
100991
101145
  }
100992
101146
  async function muxVideoWithAudio(videoPath, audioPath, outputPath, signal, config2) {
100993
- const outputDir = dirname4(outputPath);
101147
+ const outputDir = dirname5(outputPath);
100994
101148
  if (!existsSync5(outputDir)) mkdirSync2(outputDir, { recursive: true });
100995
101149
  const isWebm = outputPath.endsWith(".webm");
100996
101150
  const args = ["-i", videoPath, "-i", audioPath, "-c:v", "copy"];
@@ -101044,7 +101198,7 @@ async function applyFaststart(inputPath, outputPath, signal, config2) {
101044
101198
  // ../engine/src/services/streamingEncoder.ts
101045
101199
  import { spawn as spawn6 } from "child_process";
101046
101200
  import { existsSync as existsSync6, mkdirSync as mkdirSync3, statSync as statSync4 } from "fs";
101047
- import { dirname as dirname5 } from "path";
101201
+ import { dirname as dirname6 } from "path";
101048
101202
  function createFrameReorderBuffer(startFrame, endFrame) {
101049
101203
  let nextFrame = startFrame;
101050
101204
  let waiters = [];
@@ -101057,16 +101211,16 @@ function createFrameReorderBuffer(startFrame, endFrame) {
101057
101211
  }
101058
101212
  };
101059
101213
  return {
101060
- waitForFrame: (frame) => new Promise((resolve12) => {
101061
- waiters.push({ frame, resolve: resolve12 });
101214
+ waitForFrame: (frame) => new Promise((resolve13) => {
101215
+ waiters.push({ frame, resolve: resolve13 });
101062
101216
  resolveWaiters();
101063
101217
  }),
101064
101218
  advanceTo: (frame) => {
101065
101219
  nextFrame = frame;
101066
101220
  resolveWaiters();
101067
101221
  },
101068
- waitForAllDone: () => new Promise((resolve12) => {
101069
- waiters.push({ frame: endFrame, resolve: resolve12 });
101222
+ waitForAllDone: () => new Promise((resolve13) => {
101223
+ waiters.push({ frame: endFrame, resolve: resolve13 });
101070
101224
  resolveWaiters();
101071
101225
  })
101072
101226
  };
@@ -101151,7 +101305,7 @@ function buildStreamingArgs(options, outputPath, gpuEncoder = null) {
101151
101305
  return args;
101152
101306
  }
101153
101307
  async function spawnStreamingEncoder(outputPath, options, signal, config2) {
101154
- const outputDir = dirname5(outputPath);
101308
+ const outputDir = dirname6(outputPath);
101155
101309
  if (!existsSync6(outputDir)) mkdirSync3(outputDir, { recursive: true });
101156
101310
  let gpuEncoder = null;
101157
101311
  if (options.useGpu) {
@@ -101166,7 +101320,7 @@ async function spawnStreamingEncoder(outputPath, options, signal, config2) {
101166
101320
  let stderr = "";
101167
101321
  let exitCode = null;
101168
101322
  let exitPromiseResolve = null;
101169
- const exitPromise = new Promise((resolve12) => exitPromiseResolve = resolve12);
101323
+ const exitPromise = new Promise((resolve13) => exitPromiseResolve = resolve13);
101170
101324
  ffmpeg.stderr?.on("data", (data) => {
101171
101325
  stderr += data.toString();
101172
101326
  });
@@ -101210,8 +101364,8 @@ Process error: ${err.message}`;
101210
101364
  clearTimeout(timer2);
101211
101365
  if (signal) signal.removeEventListener("abort", onAbort);
101212
101366
  if (ffmpeg.stdin && !ffmpeg.stdin.destroyed) {
101213
- await new Promise((resolve12) => {
101214
- ffmpeg.stdin.end(() => resolve12());
101367
+ await new Promise((resolve13) => {
101368
+ ffmpeg.stdin.end(() => resolve13());
101215
101369
  });
101216
101370
  }
101217
101371
  await exitPromise;
@@ -101243,12 +101397,12 @@ Process error: ${err.message}`;
101243
101397
  // ../engine/src/services/videoFrameExtractor.ts
101244
101398
  import { spawn as spawn8 } from "child_process";
101245
101399
  import { existsSync as existsSync8, mkdirSync as mkdirSync5, readdirSync as readdirSync4, rmSync } from "fs";
101246
- import { join as join7 } from "path";
101400
+ import { join as join8 } from "path";
101247
101401
 
101248
101402
  // ../engine/src/utils/ffprobe.ts
101249
101403
  import { spawn as spawn7 } from "child_process";
101250
101404
  function runFfprobe(args) {
101251
- return new Promise((resolve12, reject) => {
101405
+ return new Promise((resolve13, reject) => {
101252
101406
  const proc = spawn7("ffprobe", args);
101253
101407
  let stdout = "";
101254
101408
  let stderr = "";
@@ -101262,7 +101416,7 @@ function runFfprobe(args) {
101262
101416
  if (code !== 0) {
101263
101417
  reject(new Error(`[FFmpeg] ffprobe exited with code ${code}: ${stderr}`));
101264
101418
  } else {
101265
- resolve12(stdout);
101419
+ resolve13(stdout);
101266
101420
  }
101267
101421
  });
101268
101422
  proc.on("error", (err) => {
@@ -101421,7 +101575,7 @@ async function analyzeKeyframeIntervalsUncached(filePath) {
101421
101575
  // ../engine/src/utils/urlDownloader.ts
101422
101576
  import { createWriteStream as createWriteStream2, existsSync as existsSync7, mkdirSync as mkdirSync4 } from "fs";
101423
101577
  import { createHash } from "crypto";
101424
- import { join as join6, extname as extname2 } from "path";
101578
+ import { join as join7, extname as extname2 } from "path";
101425
101579
  import { Readable } from "stream";
101426
101580
  import { finished } from "stream/promises";
101427
101581
  var downloadPathCache = /* @__PURE__ */ new Map();
@@ -101445,7 +101599,7 @@ async function downloadToTemp(url, destDir, timeoutMs = 3e5) {
101445
101599
  mkdirSync4(destDir, { recursive: true });
101446
101600
  }
101447
101601
  const filename = getFilenameFromUrl(url);
101448
- const localPath = join6(destDir, filename);
101602
+ const localPath = join7(destDir, filename);
101449
101603
  if (existsSync7(localPath)) {
101450
101604
  downloadPathCache.set(url, localPath);
101451
101605
  return localPath;
@@ -101488,19 +101642,15 @@ function isHttpUrl(path12) {
101488
101642
  function parseVideoElements(html) {
101489
101643
  const videos = [];
101490
101644
  const { document: document2 } = parseHTML(html);
101491
- const videoEls = Array.from(
101492
- /* @__PURE__ */ new Set([
101493
- ...Array.from(document2.querySelectorAll("video[id][src]")),
101494
- ...Array.from(document2.querySelectorAll("video[src][data-start]"))
101495
- ])
101496
- );
101497
- videoEls.forEach((el, i) => {
101498
- if (!el.id) el.id = `hf-video-${i}`;
101499
- });
101645
+ const videoEls = document2.querySelectorAll("video[src]");
101646
+ let autoIdCounter = 0;
101500
101647
  for (const el of videoEls) {
101501
- const id = el.getAttribute("id");
101502
101648
  const src = el.getAttribute("src");
101503
- if (!id || !src) continue;
101649
+ if (!src) continue;
101650
+ const id = el.getAttribute("id") || `hf-video-${autoIdCounter++}`;
101651
+ if (!el.getAttribute("id")) {
101652
+ el.setAttribute("id", id);
101653
+ }
101504
101654
  const startAttr = el.getAttribute("data-start");
101505
101655
  const endAttr = el.getAttribute("data-end");
101506
101656
  const durationAttr = el.getAttribute("data-duration");
@@ -101529,11 +101679,11 @@ function parseVideoElements(html) {
101529
101679
  async function extractVideoFramesRange(videoPath, videoId, startTime, duration, options, signal, config2) {
101530
101680
  const ffmpegProcessTimeout = config2?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
101531
101681
  const { fps, outputDir, quality = 95, format: format3 = "jpg" } = options;
101532
- const videoOutputDir = join7(outputDir, videoId);
101682
+ const videoOutputDir = join8(outputDir, videoId);
101533
101683
  if (!existsSync8(videoOutputDir)) mkdirSync5(videoOutputDir, { recursive: true });
101534
101684
  const metadata = await extractVideoMetadata(videoPath);
101535
101685
  const framePattern = `frame_%05d.${format3}`;
101536
- const outputPattern = join7(videoOutputDir, framePattern);
101686
+ const outputPattern = join8(videoOutputDir, framePattern);
101537
101687
  const args = [
101538
101688
  "-ss",
101539
101689
  String(startTime),
@@ -101548,7 +101698,7 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
101548
101698
  ];
101549
101699
  if (format3 === "png") args.push("-compression_level", "6");
101550
101700
  args.push("-y", outputPattern);
101551
- return new Promise((resolve12, reject) => {
101701
+ return new Promise((resolve13, reject) => {
101552
101702
  const ffmpeg = spawn8("ffmpeg", args);
101553
101703
  let stderr = "";
101554
101704
  const onAbort = () => {
@@ -101581,9 +101731,9 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
101581
101731
  const framePaths = /* @__PURE__ */ new Map();
101582
101732
  const files = readdirSync4(videoOutputDir).filter((f) => f.startsWith("frame_") && f.endsWith(`.${format3}`)).sort();
101583
101733
  files.forEach((file, index) => {
101584
- framePaths.set(index, join7(videoOutputDir, file));
101734
+ framePaths.set(index, join8(videoOutputDir, file));
101585
101735
  });
101586
- resolve12({
101736
+ resolve13({
101587
101737
  videoId,
101588
101738
  srcPath: videoPath,
101589
101739
  outputDir: videoOutputDir,
@@ -101618,10 +101768,10 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2)
101618
101768
  try {
101619
101769
  let videoPath = video.src;
101620
101770
  if (!videoPath.startsWith("/") && !isHttpUrl(videoPath)) {
101621
- videoPath = join7(baseDir, videoPath);
101771
+ videoPath = join8(baseDir, videoPath);
101622
101772
  }
101623
101773
  if (isHttpUrl(videoPath)) {
101624
- const downloadDir = join7(options.outputDir, "_downloads");
101774
+ const downloadDir = join8(options.outputDir, "_downloads");
101625
101775
  mkdirSync5(downloadDir, { recursive: true });
101626
101776
  videoPath = await downloadToTemp(videoPath, downloadDir);
101627
101777
  }
@@ -101865,7 +102015,7 @@ function createVideoFrameInjector(frameLookup, config2) {
101865
102015
 
101866
102016
  // ../engine/src/services/audioMixer.ts
101867
102017
  import { existsSync as existsSync9, mkdirSync as mkdirSync6, rmSync as rmSync2 } from "fs";
101868
- import { join as join8, dirname as dirname6 } from "path";
102018
+ import { join as join9, dirname as dirname7 } from "path";
101869
102019
  function parseAudioElements(html) {
101870
102020
  const elements = [];
101871
102021
  const { document: document2 } = parseHTML(html);
@@ -101915,7 +102065,7 @@ function parseAudioElements(html) {
101915
102065
  }
101916
102066
  async function extractAudioFromVideo(videoPath, outputPath, options, signal, config2) {
101917
102067
  const ffmpegProcessTimeout = config2?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
101918
- const outputDir = dirname6(outputPath);
102068
+ const outputDir = dirname7(outputPath);
101919
102069
  if (!existsSync9(outputDir)) mkdirSync6(outputDir, { recursive: true });
101920
102070
  const args = ["-i", videoPath];
101921
102071
  if (options?.startTime !== void 0) args.push("-ss", String(options.startTime));
@@ -101942,7 +102092,7 @@ async function extractAudioFromVideo(videoPath, outputPath, options, signal, con
101942
102092
  }
101943
102093
  async function prepareAudioTrack(srcPath, outputPath, mediaStart, duration, signal, config2) {
101944
102094
  const ffmpegProcessTimeout = config2?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
101945
- const outputDir = dirname6(outputPath);
102095
+ const outputDir = dirname7(outputPath);
101946
102096
  if (!existsSync9(outputDir)) mkdirSync6(outputDir, { recursive: true });
101947
102097
  const args = [
101948
102098
  "-ss",
@@ -101978,7 +102128,7 @@ async function prepareAudioTrack(srcPath, outputPath, mediaStart, duration, sign
101978
102128
  }
101979
102129
  async function generateSilence(outputPath, duration, signal, config2) {
101980
102130
  const ffmpegProcessTimeout = config2?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
101981
- const outputDir = dirname6(outputPath);
102131
+ const outputDir = dirname7(outputPath);
101982
102132
  if (!existsSync9(outputDir)) mkdirSync6(outputDir, { recursive: true });
101983
102133
  const args = [
101984
102134
  "-f",
@@ -102021,7 +102171,7 @@ async function mixAudioTracks(tracks, outputPath, totalDuration, signal, config2
102021
102171
  error: result2.error
102022
102172
  };
102023
102173
  }
102024
- const outputDir = dirname6(outputPath);
102174
+ const outputDir = dirname7(outputPath);
102025
102175
  if (!existsSync9(outputDir)) mkdirSync6(outputDir, { recursive: true });
102026
102176
  const inputs = [];
102027
102177
  const filterParts = [];
@@ -102093,7 +102243,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
102093
102243
  try {
102094
102244
  let srcPath = element.src;
102095
102245
  if (!srcPath.startsWith("/") && !isHttpUrl(srcPath)) {
102096
- srcPath = join8(baseDir, srcPath);
102246
+ srcPath = join9(baseDir, srcPath);
102097
102247
  }
102098
102248
  if (isHttpUrl(srcPath)) {
102099
102249
  try {
@@ -102116,7 +102266,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
102116
102266
  }
102117
102267
  let audioSrcPath = srcPath;
102118
102268
  if (element.type === "video") {
102119
- const extractedPath = join8(workDir, `${element.id}-extracted.wav`);
102269
+ const extractedPath = join9(workDir, `${element.id}-extracted.wav`);
102120
102270
  const extractResult = await extractAudioFromVideo(
102121
102271
  srcPath,
102122
102272
  extractedPath,
@@ -102133,7 +102283,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
102133
102283
  }
102134
102284
  audioSrcPath = extractedPath;
102135
102285
  } else {
102136
- const trimmedPath = join8(workDir, `${element.id}-trimmed.wav`);
102286
+ const trimmedPath = join9(workDir, `${element.id}-trimmed.wav`);
102137
102287
  const prepResult = await prepareAudioTrack(
102138
102288
  srcPath,
102139
102289
  trimmedPath,
@@ -102178,7 +102328,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
102178
102328
  import { cpus, freemem, totalmem } from "os";
102179
102329
  import { existsSync as existsSync10, mkdirSync as mkdirSync7, readdirSync as readdirSync5 } from "fs";
102180
102330
  import { copyFile, rename as rename2 } from "fs/promises";
102181
- import { join as join9 } from "path";
102331
+ import { join as join10 } from "path";
102182
102332
  var MEMORY_PER_WORKER_MB = 256;
102183
102333
  var MIN_WORKERS = 1;
102184
102334
  var ABSOLUTE_MAX_WORKERS = 10;
@@ -102226,7 +102376,7 @@ function distributeFrames(totalFrames, workerCount, workDir) {
102226
102376
  workerId: i,
102227
102377
  startFrame,
102228
102378
  endFrame,
102229
- outputDir: join9(workDir, `worker-${i}`)
102379
+ outputDir: join10(workDir, `worker-${i}`)
102230
102380
  });
102231
102381
  }
102232
102382
  return tasks;
@@ -102333,8 +102483,8 @@ async function mergeWorkerFrames(workDir, tasks, outputDir) {
102333
102483
  }
102334
102484
  const files = readdirSync5(task.outputDir).filter((f) => f.startsWith("frame_") && (f.endsWith(".jpg") || f.endsWith(".png"))).sort();
102335
102485
  const copyTasks = files.map(async (file) => {
102336
- const sourcePath = join9(task.outputDir, file);
102337
- const targetPath = join9(outputDir, file);
102486
+ const sourcePath = join10(task.outputDir, file);
102487
+ const targetPath = join10(outputDir, file);
102338
102488
  try {
102339
102489
  await rename2(sourcePath, targetPath);
102340
102490
  } catch {
@@ -104828,7 +104978,7 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
104828
104978
  });
104829
104979
  if (!chunk) {
104830
104980
  if (i === 1) {
104831
- await new Promise((resolve12) => setTimeout(resolve12));
104981
+ await new Promise((resolve13) => setTimeout(resolve13));
104832
104982
  maxReadCount = 3;
104833
104983
  continue;
104834
104984
  }
@@ -104972,33 +105122,33 @@ var serve = (options, listeningListener) => {
104972
105122
  };
104973
105123
 
104974
105124
  // src/services/renderOrchestrator.ts
104975
- import { join as join12, dirname as dirname9, resolve as resolve8 } from "path";
105125
+ import { join as join13, dirname as dirname10, resolve as resolve9 } from "path";
104976
105126
  import { randomUUID } from "crypto";
104977
105127
  import { freemem as freemem2 } from "os";
104978
105128
  import { fileURLToPath as fileURLToPath3 } from "url";
104979
105129
 
104980
105130
  // src/services/fileServer.ts
104981
105131
  import { readFileSync as readFileSync6, existsSync as existsSync12, statSync as statSync5 } from "node:fs";
104982
- import { join as join10, extname as extname3 } from "node:path";
105132
+ import { join as join11, extname as extname3 } from "node:path";
104983
105133
 
104984
105134
  // src/services/hyperframeRuntimeLoader.ts
104985
105135
  import { createHash as createHash2 } from "node:crypto";
104986
105136
  import { existsSync as existsSync11, readFileSync as readFileSync5 } from "node:fs";
104987
- import { dirname as dirname7, resolve as resolve6 } from "node:path";
105137
+ import { dirname as dirname8, resolve as resolve7 } from "node:path";
104988
105138
  import { fileURLToPath as fileURLToPath2 } from "node:url";
104989
- var PRODUCER_DIR = dirname7(fileURLToPath2(import.meta.url));
104990
- var SIBLING_MANIFEST_PATH = resolve6(PRODUCER_DIR, "hyperframe.manifest.json");
104991
- var MODULE_RELATIVE_MANIFEST_PATH = resolve6(
105139
+ var PRODUCER_DIR = dirname8(fileURLToPath2(import.meta.url));
105140
+ var SIBLING_MANIFEST_PATH = resolve7(PRODUCER_DIR, "hyperframe.manifest.json");
105141
+ var MODULE_RELATIVE_MANIFEST_PATH = resolve7(
104992
105142
  PRODUCER_DIR,
104993
105143
  "../../../core/dist/hyperframe.manifest.json"
104994
105144
  );
104995
105145
  var CWD_RELATIVE_MANIFEST_PATHS = [
104996
105146
  // When bundled to a single file (dist/public-server.js), the manifest
104997
105147
  // is copied as a sibling by build.mjs
104998
- resolve6(PRODUCER_DIR, "hyperframe.manifest.json"),
104999
- resolve6(process.cwd(), "packages/core/dist/hyperframe.manifest.json"),
105000
- resolve6(process.cwd(), "../core/dist/hyperframe.manifest.json"),
105001
- resolve6(process.cwd(), "core/dist/hyperframe.manifest.json")
105148
+ resolve7(PRODUCER_DIR, "hyperframe.manifest.json"),
105149
+ resolve7(process.cwd(), "packages/core/dist/hyperframe.manifest.json"),
105150
+ resolve7(process.cwd(), "../core/dist/hyperframe.manifest.json"),
105151
+ resolve7(process.cwd(), "core/dist/hyperframe.manifest.json")
105002
105152
  ];
105003
105153
  function resolveHyperframeManifestPath() {
105004
105154
  if (process.env.PRODUCER_HYPERFRAME_MANIFEST_PATH) {
@@ -105034,7 +105184,7 @@ function resolveVerifiedHyperframeRuntime() {
105034
105184
  `[HyperframeRuntimeLoader] Invalid manifest at ${manifestPath}; missing iife artifact or sha256.`
105035
105185
  );
105036
105186
  }
105037
- const runtimePath = resolve6(dirname7(manifestPath), runtimeFileName);
105187
+ const runtimePath = resolve7(dirname8(manifestPath), runtimeFileName);
105038
105188
  if (!existsSync11(runtimePath)) {
105039
105189
  throw new Error(`[HyperframeRuntimeLoader] Missing runtime artifact at ${runtimePath}.`);
105040
105190
  }
@@ -105285,11 +105435,11 @@ function createFileServer2(options) {
105285
105435
  let requestPath = c.req.path;
105286
105436
  if (requestPath === "/") requestPath = "/index.html";
105287
105437
  const relativePath = requestPath.replace(/^\//, "");
105288
- const compiledPath = compiledDir ? join10(compiledDir, relativePath) : null;
105438
+ const compiledPath = compiledDir ? join11(compiledDir, relativePath) : null;
105289
105439
  const hasCompiledFile = Boolean(
105290
105440
  compiledPath && existsSync12(compiledPath) && statSync5(compiledPath).isFile()
105291
105441
  );
105292
- const filePath = hasCompiledFile ? compiledPath : join10(projectDir, relativePath);
105442
+ const filePath = hasCompiledFile ? compiledPath : join11(projectDir, relativePath);
105293
105443
  if (!existsSync12(filePath) || !statSync5(filePath).isFile()) {
105294
105444
  return c.text("Not found", 404);
105295
105445
  }
@@ -105307,22 +105457,29 @@ function createFileServer2(options) {
105307
105457
  headers: { "Content-Type": contentType }
105308
105458
  });
105309
105459
  });
105310
- return new Promise((resolve12) => {
105460
+ return new Promise((resolve13) => {
105461
+ const connections = /* @__PURE__ */ new Set();
105311
105462
  const server = serve({ fetch: app.fetch, port }, (info) => {
105312
- const actualPort = info.port;
105313
- const url = `http://localhost:${actualPort}`;
105314
- resolve12({
105315
- url,
105316
- port: actualPort,
105317
- close: () => server.close()
105463
+ resolve13({
105464
+ url: `http://localhost:${info.port}`,
105465
+ port: info.port,
105466
+ close: () => {
105467
+ for (const socket of connections) socket.destroy();
105468
+ connections.clear();
105469
+ server.close();
105470
+ }
105318
105471
  });
105319
105472
  });
105473
+ server.on("connection", (socket) => {
105474
+ connections.add(socket);
105475
+ socket.on("close", () => connections.delete(socket));
105476
+ });
105320
105477
  });
105321
105478
  }
105322
105479
 
105323
105480
  // src/services/htmlCompiler.ts
105324
105481
  import { readFileSync as readFileSync7, existsSync as existsSync13, mkdirSync as mkdirSync8 } from "fs";
105325
- import { join as join11, dirname as dirname8, resolve as resolve7 } from "path";
105482
+ import { join as join12, dirname as dirname9, resolve as resolve8 } from "path";
105326
105483
 
105327
105484
  // src/services/fontData.generated.ts
105328
105485
  var EMBEDDED_FONT_DATA = /* @__PURE__ */ new Map([
@@ -105575,7 +105732,7 @@ async function resolveMediaDuration(src, mediaStart, baseDir, downloadDir, tagNa
105575
105732
  return { duration: 0, resolvedPath: src };
105576
105733
  }
105577
105734
  } else if (!filePath.startsWith("/")) {
105578
- filePath = join11(baseDir, filePath);
105735
+ filePath = join12(baseDir, filePath);
105579
105736
  }
105580
105737
  if (!existsSync13(filePath)) {
105581
105738
  return { duration: 0, resolvedPath: filePath };
@@ -105641,7 +105798,7 @@ async function parseSubCompositions(html, projectDir, downloadDir, parentOffset
105641
105798
  const elEnd = elEndRaw ? parseFloat(elEndRaw) : Infinity;
105642
105799
  const absoluteStart = parentOffset + elStart;
105643
105800
  const absoluteEnd = Math.min(parentEnd, isFinite(elEnd) ? parentOffset + elEnd : Infinity);
105644
- const filePath = resolve7(projectDir, srcPath);
105801
+ const filePath = resolve8(projectDir, srcPath);
105645
105802
  if (visited.has(filePath)) {
105646
105803
  continue;
105647
105804
  }
@@ -105657,7 +105814,7 @@ async function parseSubCompositions(html, projectDir, downloadDir, parentOffset
105657
105814
  workItems.map(async (item) => {
105658
105815
  const { html: compiledSub } = await compileHtmlFile(
105659
105816
  item.rawSubHtml,
105660
- dirname8(item.filePath),
105817
+ dirname9(item.filePath),
105661
105818
  downloadDir
105662
105819
  );
105663
105820
  const nested = await parseSubCompositions(
@@ -105836,12 +105993,13 @@ function inlineSubCompositions(html, subCompositions, projectDir) {
105836
105993
  if (!hosts.length) return html;
105837
105994
  const collectedStyles = [];
105838
105995
  const collectedScripts = [];
105996
+ const collectedExternalScriptSrcs = [];
105839
105997
  for (const host of hosts) {
105840
105998
  const srcPath = host.getAttribute("data-composition-src");
105841
105999
  if (!srcPath) continue;
105842
106000
  let compHtml = subCompositions.get(srcPath) || null;
105843
106001
  if (!compHtml) {
105844
- const filePath = resolve7(projectDir, srcPath);
106002
+ const filePath = resolve8(projectDir, srcPath);
105845
106003
  if (existsSync13(filePath)) {
105846
106004
  compHtml = readFileSync7(filePath, "utf-8");
105847
106005
  }
@@ -105869,7 +106027,13 @@ function inlineSubCompositions(html, subCompositions, projectDir) {
105869
106027
  }
105870
106028
  for (const scriptEl of contentDoc.querySelectorAll("script")) {
105871
106029
  const src = (scriptEl.getAttribute("src") || "").trim();
105872
- if (src) continue;
106030
+ if (src) {
106031
+ if (!collectedExternalScriptSrcs.includes(src)) {
106032
+ collectedExternalScriptSrcs.push(src);
106033
+ }
106034
+ scriptEl.remove();
106035
+ continue;
106036
+ }
105873
106037
  const content = (scriptEl.textContent || "").trim();
105874
106038
  if (content) {
105875
106039
  const scriptMountCompId = compId || inferredCompId || "";
@@ -105896,6 +106060,13 @@ function inlineSubCompositions(html, subCompositions, projectDir) {
105896
106060
  }
105897
106061
  scriptEl.remove();
105898
106062
  }
106063
+ const rewriteTarget = innerRoot || contentDoc;
106064
+ rewriteAssetPaths(
106065
+ rewriteTarget.querySelectorAll("[src], [href]"),
106066
+ srcPath,
106067
+ (el, attr) => (el.getAttribute(attr) || "").trim(),
106068
+ (el, attr, val) => el.setAttribute(attr, val)
106069
+ );
105899
106070
  if (innerRoot) {
105900
106071
  const innerW = innerRoot.getAttribute("data-width");
105901
106072
  const innerH = innerRoot.getAttribute("data-height");
@@ -105939,6 +106110,21 @@ function inlineSubCompositions(html, subCompositions, projectDir) {
105939
106110
  styleEl.textContent = collectedStyles.join("\n\n");
105940
106111
  head.appendChild(styleEl);
105941
106112
  }
106113
+ if (collectedExternalScriptSrcs.length && body) {
106114
+ const existingScriptSrcs = new Set(
106115
+ Array.from(document2.querySelectorAll("script[src]")).map(
106116
+ (el) => (el.getAttribute("src") || "").trim()
106117
+ )
106118
+ );
106119
+ for (const src of collectedExternalScriptSrcs) {
106120
+ if (!existingScriptSrcs.has(src)) {
106121
+ const scriptEl = document2.createElement("script");
106122
+ scriptEl.setAttribute("src", src);
106123
+ body.appendChild(scriptEl);
106124
+ existingScriptSrcs.add(src);
106125
+ }
106126
+ }
106127
+ }
105942
106128
  if (collectedScripts.length && body) {
105943
106129
  const scriptEl = document2.createElement("script");
105944
106130
  scriptEl.textContent = collectedScripts.join("\n;\n");
@@ -105985,11 +106171,11 @@ async function compileForRender(projectDir, htmlPath, downloadDir) {
105985
106171
  );
105986
106172
  const mainVideos = parseVideoElements(html);
105987
106173
  const mainAudios = parseAudioElements(html);
105988
- const videos = dedupeElementsById([...subVideos, ...mainVideos]);
105989
- const audios = dedupeElementsById([...subAudios, ...mainAudios]);
106174
+ const videos = dedupeElementsById([...mainVideos, ...subVideos]);
106175
+ const audios = dedupeElementsById([...mainAudios, ...subAudios]);
105990
106176
  for (const video of videos) {
105991
106177
  if (isHttpUrl(video.src)) continue;
105992
- const videoPath = resolve7(projectDir, video.src);
106178
+ const videoPath = resolve8(projectDir, video.src);
105993
106179
  const reencode = `ffmpeg -i "${video.src}" -c:v libx264 -r 30 -g 30 -keyint_min 30 -movflags +faststart -c:a copy output.mp4`;
105994
106180
  Promise.all([analyzeKeyframeIntervals(videoPath), extractVideoMetadata(videoPath)]).then(([analysis, metadata]) => {
105995
106181
  if (analysis.isProblematic) {
@@ -106005,22 +106191,6 @@ async function compileForRender(projectDir, htmlPath, downloadDir) {
106005
106191
  }).catch(() => {
106006
106192
  });
106007
106193
  }
106008
- const autoIdVideos = videos.filter((v) => v.id.startsWith("hf-video-"));
106009
- let htmlWithIds = html;
106010
- if (autoIdVideos.length > 0) {
106011
- const { document: idDoc } = parseHTML(html);
106012
- let changed = false;
106013
- for (const v of autoIdVideos) {
106014
- const el = idDoc.querySelector(`video[src="${v.src}"]:not([id])`);
106015
- if (el) {
106016
- el.id = v.id;
106017
- changed = true;
106018
- }
106019
- }
106020
- if (changed) {
106021
- htmlWithIds = idDoc.documentElement?.outerHTML ?? html;
106022
- }
106023
- }
106024
106194
  const { document: document2 } = parseHTML(html);
106025
106195
  const rootEl = document2.querySelector("[data-composition-id]");
106026
106196
  const width = rootEl ? parseInt(rootEl.getAttribute("data-width") || "1080", 10) : 1080;
@@ -106029,7 +106199,7 @@ async function compileForRender(projectDir, htmlPath, downloadDir) {
106029
106199
  rootEl.getAttribute("data-duration") || rootEl.getAttribute("data-composition-duration") || "0"
106030
106200
  ) : 0;
106031
106201
  return {
106032
- html: htmlWithIds,
106202
+ html,
106033
106203
  subCompositions,
106034
106204
  videos,
106035
106205
  audios,
@@ -106119,8 +106289,8 @@ async function recompileWithResolutions(compiled, resolutions, projectDir, downl
106119
106289
  } = await parseSubCompositions(html, projectDir, downloadDir);
106120
106290
  const mainVideos = parseVideoElements(html);
106121
106291
  const mainAudios = parseAudioElements(html);
106122
- const videos = dedupeElementsById([...subVideos, ...mainVideos]);
106123
- const audios = dedupeElementsById([...subAudios, ...mainAudios]);
106292
+ const videos = dedupeElementsById([...mainVideos, ...subVideos]);
106293
+ const audios = dedupeElementsById([...mainAudios, ...subAudios]);
106124
106294
  const remaining = compiled.unresolvedCompositions.filter(
106125
106295
  (c) => !resolutions.some((r) => r.id === c.id)
106126
106296
  );
@@ -106231,12 +106401,12 @@ function installDebugLogger(logPath, log = defaultLogger) {
106231
106401
  };
106232
106402
  }
106233
106403
  function writeCompiledArtifacts(compiled, workDir, includeSummary) {
106234
- const compileDir = join12(workDir, "compiled");
106404
+ const compileDir = join13(workDir, "compiled");
106235
106405
  mkdirSync9(compileDir, { recursive: true });
106236
- writeFileSync3(join12(compileDir, "index.html"), compiled.html, "utf-8");
106406
+ writeFileSync3(join13(compileDir, "index.html"), compiled.html, "utf-8");
106237
106407
  for (const [srcPath, html] of compiled.subCompositions) {
106238
- const outPath = join12(compileDir, srcPath);
106239
- mkdirSync9(dirname9(outPath), { recursive: true });
106408
+ const outPath = join13(compileDir, srcPath);
106409
+ mkdirSync9(dirname10(outPath), { recursive: true });
106240
106410
  writeFileSync3(outPath, html, "utf-8");
106241
106411
  }
106242
106412
  if (includeSummary) {
@@ -106260,7 +106430,7 @@ function writeCompiledArtifacts(compiled, workDir, includeSummary) {
106260
106430
  })),
106261
106431
  subCompositions: Array.from(compiled.subCompositions.keys())
106262
106432
  };
106263
- writeFileSync3(join12(compileDir, "summary.json"), JSON.stringify(summary, null, 2), "utf-8");
106433
+ writeFileSync3(join13(compileDir, "summary.json"), JSON.stringify(summary, null, 2), "utf-8");
106264
106434
  }
106265
106435
  }
106266
106436
  function createRenderJob(config2) {
@@ -106303,10 +106473,10 @@ function extractStandaloneEntryFromIndex(indexHtml, entryFile) {
106303
106473
  return document2.toString();
106304
106474
  }
106305
106475
  async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSignal) {
106306
- const moduleDir = dirname9(fileURLToPath3(import.meta.url));
106307
- const producerRoot = process.env.PRODUCER_RENDERS_DIR ? resolve8(process.env.PRODUCER_RENDERS_DIR, "..") : resolve8(moduleDir, "../..");
106308
- const debugDir = join12(producerRoot, ".debug");
106309
- const workDir = job.config.debug ? join12(debugDir, job.id) : join12(dirname9(outputPath), `work-${job.id}`);
106476
+ const moduleDir = dirname10(fileURLToPath3(import.meta.url));
106477
+ const producerRoot = process.env.PRODUCER_RENDERS_DIR ? resolve9(process.env.PRODUCER_RENDERS_DIR, "..") : resolve9(moduleDir, "../..");
106478
+ const debugDir = join13(producerRoot, ".debug");
106479
+ const workDir = job.config.debug ? join13(debugDir, job.id) : join13(dirname10(outputPath), `work-${job.id}`);
106310
106480
  const pipelineStart = Date.now();
106311
106481
  const log = job.config.logger ?? defaultLogger;
106312
106482
  let fileServer = null;
@@ -106314,7 +106484,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
106314
106484
  let lastBrowserConsole = [];
106315
106485
  let restoreLogger = null;
106316
106486
  const perfStages = {};
106317
- const perfOutputPath = join12(workDir, "perf-summary.json");
106487
+ const perfOutputPath = join13(workDir, "perf-summary.json");
106318
106488
  const cfg = { ...job.config.producerConfig ?? resolveConfig() };
106319
106489
  const outputFormat = job.config.format ?? "mp4";
106320
106490
  const isWebm = outputFormat === "webm";
@@ -106334,19 +106504,19 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
106334
106504
  assertNotAborted();
106335
106505
  if (!existsSync14(workDir)) mkdirSync9(workDir, { recursive: true });
106336
106506
  if (job.config.debug) {
106337
- const logPath = join12(workDir, "render.log");
106507
+ const logPath = join13(workDir, "render.log");
106338
106508
  restoreLogger = installDebugLogger(logPath, log);
106339
106509
  }
106340
106510
  const entryFile = job.config.entryFile || "index.html";
106341
- let htmlPath = join12(projectDir, entryFile);
106511
+ let htmlPath = join13(projectDir, entryFile);
106342
106512
  if (!existsSync14(htmlPath)) {
106343
106513
  throw new Error(`Entry file not found: ${htmlPath}`);
106344
106514
  }
106345
106515
  assertNotAborted();
106346
106516
  const rawEntry = readFileSync8(htmlPath, "utf-8");
106347
106517
  if (entryFile !== "index.html" && rawEntry.trimStart().startsWith("<template")) {
106348
- const wrapperPath = join12(workDir, "standalone-entry.html");
106349
- const projectIndexPath = join12(projectDir, "index.html");
106518
+ const wrapperPath = join13(workDir, "standalone-entry.html");
106519
+ const projectIndexPath = join13(projectDir, "index.html");
106350
106520
  if (!existsSync14(projectIndexPath)) {
106351
106521
  throw new Error(
106352
106522
  `Template entry file "${entryFile}" requires a project index.html to extract its render shell.`
@@ -106370,7 +106540,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
106370
106540
  const stage1Start = Date.now();
106371
106541
  updateJobStatus(job, "preprocessing", "Compiling composition", 5, onProgress);
106372
106542
  const compileStart = Date.now();
106373
- let compiled = await compileForRender(projectDir, htmlPath, join12(workDir, "downloads"));
106543
+ let compiled = await compileForRender(projectDir, htmlPath, join13(workDir, "downloads"));
106374
106544
  assertNotAborted();
106375
106545
  perfStages.compileOnlyMs = Date.now() - compileStart;
106376
106546
  writeCompiledArtifacts(compiled, workDir, Boolean(job.config.debug));
@@ -106399,7 +106569,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
106399
106569
  reasons.push(`${compiled.unresolvedCompositions.length} unresolved composition(s)`);
106400
106570
  fileServer = await createFileServer2({
106401
106571
  projectDir,
106402
- compiledDir: join12(workDir, "compiled"),
106572
+ compiledDir: join13(workDir, "compiled"),
106403
106573
  port: 0
106404
106574
  });
106405
106575
  assertNotAborted();
@@ -106412,7 +106582,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
106412
106582
  };
106413
106583
  probeSession = await createCaptureSession(
106414
106584
  fileServer.url,
106415
- join12(workDir, "probe"),
106585
+ join13(workDir, "probe"),
106416
106586
  captureOpts,
106417
106587
  null,
106418
106588
  cfg
@@ -106444,7 +106614,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
106444
106614
  compiled,
106445
106615
  resolutions,
106446
106616
  projectDir,
106447
- join12(workDir, "downloads")
106617
+ join13(workDir, "downloads")
106448
106618
  );
106449
106619
  assertNotAborted();
106450
106620
  composition.videos = compiled.videos;
@@ -106541,7 +106711,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
106541
106711
  const extractionResult = await extractAllVideoFrames(
106542
106712
  composition.videos,
106543
106713
  projectDir,
106544
- { fps: job.config.fps, outputDir: join12(workDir, "video-frames") },
106714
+ { fps: job.config.fps, outputDir: join13(workDir, "video-frames") },
106545
106715
  abortSignal
106546
106716
  );
106547
106717
  assertNotAborted();
@@ -106573,13 +106743,13 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
106573
106743
  }
106574
106744
  const stage3Start = Date.now();
106575
106745
  updateJobStatus(job, "preprocessing", "Processing audio tracks", 20, onProgress);
106576
- const audioOutputPath = join12(workDir, "audio.aac");
106746
+ const audioOutputPath = join13(workDir, "audio.aac");
106577
106747
  let hasAudio = false;
106578
106748
  if (composition.audios.length > 0) {
106579
106749
  const audioResult = await processCompositionAudio(
106580
106750
  composition.audios,
106581
106751
  projectDir,
106582
- join12(workDir, "audio-work"),
106752
+ join13(workDir, "audio-work"),
106583
106753
  audioOutputPath,
106584
106754
  job.duration,
106585
106755
  abortSignal
@@ -106595,12 +106765,12 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
106595
106765
  if (!fileServer) {
106596
106766
  fileServer = await createFileServer2({
106597
106767
  projectDir,
106598
- compiledDir: join12(workDir, "compiled"),
106768
+ compiledDir: join13(workDir, "compiled"),
106599
106769
  port: 0
106600
106770
  });
106601
106771
  assertNotAborted();
106602
106772
  }
106603
- const framesDir = join12(workDir, "captured-frames");
106773
+ const framesDir = join13(workDir, "captured-frames");
106604
106774
  if (!existsSync14(framesDir)) mkdirSync9(framesDir, { recursive: true });
106605
106775
  const captureOptions = {
106606
106776
  width,
@@ -106611,7 +106781,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
106611
106781
  };
106612
106782
  const workerCount = calculateOptimalWorkers(job.totalFrames, job.config.workers, cfg);
106613
106783
  const videoExt = isWebm ? ".webm" : ".mp4";
106614
- const videoOnlyPath = join12(workDir, `video-only${videoExt}`);
106784
+ const videoOnlyPath = join13(workDir, `video-only${videoExt}`);
106615
106785
  const preset = getEncoderPreset(job.config.quality, outputFormat);
106616
106786
  job.framesRendered = 0;
106617
106787
  let streamingEncoder = null;
@@ -106890,7 +107060,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
106890
107060
  }
106891
107061
  if (job.config.debug) {
106892
107062
  if (existsSync14(outputPath)) {
106893
- const debugOutput = join12(workDir, isWebm ? "output.webm" : "output.mp4");
107063
+ const debugOutput = join13(workDir, isWebm ? "output.webm" : "output.mp4");
106894
107064
  copyFileSync2(outputPath, debugOutput);
106895
107065
  }
106896
107066
  } else {
@@ -106993,7 +107163,7 @@ import {
106993
107163
  rmSync as rmSync4,
106994
107164
  createReadStream as createReadStream2
106995
107165
  } from "node:fs";
106996
- import { resolve as resolve11, dirname as dirname10, join as join15 } from "node:path";
107166
+ import { resolve as resolve12, dirname as dirname11, join as join16 } from "node:path";
106997
107167
  import { tmpdir as tmpdir2 } from "node:os";
106998
107168
  import { parseArgs } from "node:util";
106999
107169
  import crypto2 from "node:crypto";
@@ -107149,7 +107319,7 @@ var streamSSE = (c, cb, onError) => {
107149
107319
 
107150
107320
  // src/services/hyperframeLint.ts
107151
107321
  import { existsSync as existsSync15, readFileSync as readFileSync9, statSync as statSync6 } from "node:fs";
107152
- import { resolve as resolve9, join as join13 } from "node:path";
107322
+ import { resolve as resolve10, join as join14 } from "node:path";
107153
107323
  function isStringRecord(value) {
107154
107324
  if (!value || typeof value !== "object" || Array.isArray(value)) {
107155
107325
  return false;
@@ -107176,7 +107346,7 @@ function pickEntryFile(files, preferredEntryFile) {
107176
107346
  return null;
107177
107347
  }
107178
107348
  function readProjectEntryFile(projectDir, preferredEntryFile) {
107179
- const absProjectDir = resolve9(projectDir);
107349
+ const absProjectDir = resolve10(projectDir);
107180
107350
  if (!existsSync15(absProjectDir) || !statSync6(absProjectDir).isDirectory()) {
107181
107351
  return { error: `Project directory not found: ${absProjectDir}` };
107182
107352
  }
@@ -107184,7 +107354,7 @@ function readProjectEntryFile(projectDir, preferredEntryFile) {
107184
107354
  (value) => typeof value === "string" && value.trim().length > 0
107185
107355
  );
107186
107356
  for (const entryFile of entryCandidates) {
107187
- const absoluteEntryPath = resolve9(absProjectDir, entryFile);
107357
+ const absoluteEntryPath = resolve10(absProjectDir, entryFile);
107188
107358
  if (!absoluteEntryPath.startsWith(absProjectDir)) {
107189
107359
  return { error: `Entry file must stay inside project directory: ${entryFile}` };
107190
107360
  }
@@ -107197,7 +107367,7 @@ function readProjectEntryFile(projectDir, preferredEntryFile) {
107197
107367
  }
107198
107368
  }
107199
107369
  return {
107200
- error: `No HTML entry file found in project directory: ${join13(absProjectDir, preferredEntryFile || "index.html")}`
107370
+ error: `No HTML entry file found in project directory: ${join14(absProjectDir, preferredEntryFile || "index.html")}`
107201
107371
  };
107202
107372
  }
107203
107373
  function prepareHyperframeLintBody(body) {
@@ -107238,13 +107408,13 @@ function runHyperframeLint(prepared) {
107238
107408
  }
107239
107409
 
107240
107410
  // src/utils/paths.ts
107241
- import { resolve as resolve10, basename as basename2, join as join14 } from "node:path";
107242
- var DEFAULT_RENDERS_DIR = process.env.PRODUCER_RENDERS_DIR ?? resolve10(new URL(import.meta.url).pathname, "../../..", "renders");
107411
+ import { resolve as resolve11, basename as basename2, join as join15 } from "node:path";
107412
+ var DEFAULT_RENDERS_DIR = process.env.PRODUCER_RENDERS_DIR ?? resolve11(new URL(import.meta.url).pathname, "../../..", "renders");
107243
107413
  function resolveRenderPaths(projectDir, outputPath, rendersDir = DEFAULT_RENDERS_DIR) {
107244
- const absoluteProjectDir = resolve10(projectDir);
107414
+ const absoluteProjectDir = resolve11(projectDir);
107245
107415
  const projectName = basename2(absoluteProjectDir);
107246
- const resolvedOutputPath = outputPath ?? join14(rendersDir, `${projectName}.mp4`);
107247
- const absoluteOutputPath = resolve10(resolvedOutputPath);
107416
+ const resolvedOutputPath = outputPath ?? join15(rendersDir, `${projectName}.mp4`);
107417
+ const absoluteOutputPath = resolve11(resolvedOutputPath);
107248
107418
  return { absoluteProjectDir, absoluteOutputPath };
107249
107419
  }
107250
107420
 
@@ -107264,12 +107434,12 @@ async function prepareRenderBody(body) {
107264
107434
  const options = parseRenderOptions(body);
107265
107435
  const projectDir = typeof body.projectDir === "string" ? body.projectDir : void 0;
107266
107436
  if (projectDir) {
107267
- const absProjectDir = resolve11(projectDir);
107437
+ const absProjectDir = resolve12(projectDir);
107268
107438
  if (!existsSync16(absProjectDir) || !statSync7(absProjectDir).isDirectory()) {
107269
107439
  return { error: `Project directory not found: ${absProjectDir}` };
107270
107440
  }
107271
107441
  const entry = options.entryFile || "index.html";
107272
- if (!existsSync16(resolve11(absProjectDir, entry))) {
107442
+ if (!existsSync16(resolve12(absProjectDir, entry))) {
107273
107443
  return { error: `Entry file "${entry}" not found in project directory: ${absProjectDir}` };
107274
107444
  }
107275
107445
  return { prepared: { input: { projectDir: absProjectDir, ...options } } };
@@ -107294,8 +107464,8 @@ async function prepareRenderBody(body) {
107294
107464
  }
107295
107465
  }
107296
107466
  const tempRoot = process.env.PRODUCER_TMP_PROJECT_DIR || tmpdir2();
107297
- const tempProjectDir = mkdtempSync(join15(tempRoot, "producer-project-"));
107298
- writeFileSync4(join15(tempProjectDir, "index.html"), htmlContent, "utf-8");
107467
+ const tempProjectDir = mkdtempSync(join16(tempRoot, "producer-project-"));
107468
+ writeFileSync4(join16(tempProjectDir, "index.html"), htmlContent, "utf-8");
107299
107469
  return {
107300
107470
  prepared: {
107301
107471
  input: {
@@ -107310,7 +107480,7 @@ function resolveOutputPath(projectDir, outputCandidate, rendersDir, log) {
107310
107480
  try {
107311
107481
  return resolveRenderPaths(projectDir, outputCandidate, rendersDir).absoluteOutputPath;
107312
107482
  } catch (error) {
107313
- const fallbackPath = resolve11(rendersDir, `producer-fallback-${Date.now()}.mp4`);
107483
+ const fallbackPath = resolve12(rendersDir, `producer-fallback-${Date.now()}.mp4`);
107314
107484
  log.warn("Failed to resolve output path, using fallback", {
107315
107485
  fallback: fallbackPath,
107316
107486
  error: error instanceof Error ? error.message : String(error)
@@ -107415,7 +107585,7 @@ function createRenderHandlers(options = {}) {
107415
107585
  rendersDir,
107416
107586
  log
107417
107587
  );
107418
- const outputDir = dirname10(absoluteOutputPath);
107588
+ const outputDir = dirname11(absoluteOutputPath);
107419
107589
  if (!existsSync16(outputDir)) mkdirSync10(outputDir, { recursive: true });
107420
107590
  log.info("render started", {
107421
107591
  requestId,
@@ -107524,7 +107694,7 @@ function createRenderHandlers(options = {}) {
107524
107694
  rendersDir,
107525
107695
  log
107526
107696
  );
107527
- const outputDir = dirname10(absoluteOutputPath);
107697
+ const outputDir = dirname11(absoluteOutputPath);
107528
107698
  if (!existsSync16(outputDir)) mkdirSync10(outputDir, { recursive: true });
107529
107699
  log.info("render-stream started", { requestId, projectDir: input2.projectDir });
107530
107700
  const job = createRenderJob({
@@ -107668,7 +107838,7 @@ function startServer(options = {}) {
107668
107838
  process.on("SIGINT", () => shutdown("SIGINT"));
107669
107839
  return server;
107670
107840
  }
107671
- var entryScript = process.argv[1] ? resolve11(process.argv[1]) : "";
107841
+ var entryScript = process.argv[1] ? resolve12(process.argv[1]) : "";
107672
107842
  var isPublicServerEntry = entryScript.endsWith("/public-server.js") || entryScript.endsWith("/src/server.ts");
107673
107843
  if (isPublicServerEntry) {
107674
107844
  const { values } = parseArgs({