@hyperframes/producer 0.1.9 → 0.1.11

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.
@@ -101982,7 +101982,9 @@ var INVALID_SCRIPT_CLOSE_PATTERN = /<script[^>]*>[\s\S]*?<\s*\/\s*script(?!>)/i;
101982
101982
  var WINDOW_TIMELINE_ASSIGN_PATTERN = /window\.__timelines\[\s*["']([^"']+)["']\s*\]\s*=\s*([A-Za-z_$][\w$]*)/i;
101983
101983
  var META_GSAP_KEYS = /* @__PURE__ */ new Set(["duration", "ease", "repeat", "yoyo", "overwrite", "delay"]);
101984
101984
  function lintHyperframeHtml(html, options = {}) {
101985
- const source2 = html || "";
101985
+ let source2 = html || "";
101986
+ const templateMatch = source2.match(/<template[^>]*>([\s\S]*)<\/template>/i);
101987
+ if (templateMatch?.[1]) source2 = templateMatch[1];
101986
101988
  const filePath = options.filePath;
101987
101989
  const findings = [];
101988
101990
  const seen = /* @__PURE__ */ new Set();
@@ -102339,18 +102341,20 @@ ${right2.raw}`)
102339
102341
  for (const tag of tags) {
102340
102342
  if (tag.name === "audio" || tag.name === "script" || tag.name === "style") continue;
102341
102343
  if (!readAttr(tag.raw, "data-start")) continue;
102344
+ if (readAttr(tag.raw, "data-composition-id")) continue;
102345
+ if (readAttr(tag.raw, "data-composition-src")) continue;
102342
102346
  const classAttr = readAttr(tag.raw, "class") || "";
102343
102347
  const styleAttr = readAttr(tag.raw, "style") || "";
102344
102348
  const hasClip = classAttr.split(/\s+/).includes("clip");
102345
- const hasHiddenStyle = /visibility\s*:\s*hidden/i.test(styleAttr);
102349
+ const hasHiddenStyle = /visibility\s*:\s*hidden/i.test(styleAttr) || /opacity\s*:\s*0/i.test(styleAttr);
102346
102350
  if (!hasClip && !hasHiddenStyle) {
102347
102351
  const elementId = readAttr(tag.raw, "id") || void 0;
102348
102352
  pushFinding({
102349
102353
  code: "timed_element_missing_visibility_hidden",
102350
- severity: "warning",
102351
- message: `<${tag.name}${elementId ? ` id="${elementId}"` : ""}> has data-start but no class="clip" or visibility:hidden. The framework needs elements to start hidden so it can manage their lifecycle.`,
102354
+ severity: "info",
102355
+ 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.`,
102352
102356
  elementId,
102353
- fixHint: 'Add class="clip" to the element (with CSS: .clip { visibility: hidden; }).',
102357
+ fixHint: 'Add class="clip" (with CSS: .clip { visibility: hidden; }) or style="opacity:0" if the element should start hidden.',
102354
102358
  snippet: truncateSnippet(tag.raw)
102355
102359
  });
102356
102360
  }
@@ -102379,6 +102383,76 @@ ${right2.raw}`)
102379
102383
  });
102380
102384
  }
102381
102385
  }
102386
+ for (const script of scripts) {
102387
+ const templateLiteralSelectorPattern = /(?:querySelector|querySelectorAll)\s*\(\s*`[^`]*\$\{[^}]+\}[^`]*`\s*\)/g;
102388
+ let tlMatch;
102389
+ while ((tlMatch = templateLiteralSelectorPattern.exec(script.content)) !== null) {
102390
+ pushFinding({
102391
+ code: "template_literal_selector",
102392
+ severity: "error",
102393
+ message: "querySelector uses a template literal variable (e.g. `${compId}`). The HTML bundler's CSS parser crashes on these. Use a hardcoded string instead.",
102394
+ file: filePath,
102395
+ fixHint: "Replace the template literal variable with a hardcoded string. The bundler's CSS parser cannot handle interpolated variables in script content.",
102396
+ snippet: truncateSnippet(tlMatch[0])
102397
+ });
102398
+ }
102399
+ }
102400
+ {
102401
+ const cssTranslateSelectors = /* @__PURE__ */ new Map();
102402
+ const cssScaleSelectors = /* @__PURE__ */ new Map();
102403
+ for (const style of styles) {
102404
+ for (const [, selector, body] of style.content.matchAll(
102405
+ /([#.][a-zA-Z0-9_-]+)\s*\{([^}]+)\}/g
102406
+ )) {
102407
+ const tMatch = body?.match(/transform\s*:\s*([^;]+)/);
102408
+ if (!tMatch || !tMatch[1]) continue;
102409
+ const transformVal = tMatch[1].trim();
102410
+ if (/translate/i.test(transformVal)) {
102411
+ cssTranslateSelectors.set((selector ?? "").trim(), transformVal);
102412
+ }
102413
+ if (/scale/i.test(transformVal)) {
102414
+ cssScaleSelectors.set((selector ?? "").trim(), transformVal);
102415
+ }
102416
+ }
102417
+ }
102418
+ if (cssTranslateSelectors.size > 0 || cssScaleSelectors.size > 0) {
102419
+ for (const script of scripts) {
102420
+ if (!/gsap\.timeline/.test(script.content)) continue;
102421
+ const windows = extractGsapWindows(script.content);
102422
+ const conflicts = /* @__PURE__ */ new Map();
102423
+ for (const win of windows) {
102424
+ if (win.method === "fromTo") continue;
102425
+ const sel = win.targetSelector;
102426
+ const cssKey = sel.startsWith("#") || sel.startsWith(".") ? sel : `#${sel}`;
102427
+ const translateProps = win.properties.filter(
102428
+ (p) => ["x", "y", "xPercent", "yPercent"].includes(p)
102429
+ );
102430
+ const scaleProps = win.properties.filter((p) => p === "scale");
102431
+ const cssFromTranslate = translateProps.length > 0 ? cssTranslateSelectors.get(cssKey) : void 0;
102432
+ const cssFromScale = scaleProps.length > 0 ? cssScaleSelectors.get(cssKey) : void 0;
102433
+ if (!cssFromTranslate && !cssFromScale) continue;
102434
+ const existing = conflicts.get(sel) ?? {
102435
+ cssTransform: [cssFromTranslate, cssFromScale].filter(Boolean).join(" "),
102436
+ props: /* @__PURE__ */ new Set(),
102437
+ raw: win.raw
102438
+ };
102439
+ for (const p of [...translateProps, ...scaleProps]) existing.props.add(p);
102440
+ conflicts.set(sel, existing);
102441
+ }
102442
+ for (const [sel, { cssTransform, props, raw: raw2 }] of conflicts) {
102443
+ const propList = [...props].join("/");
102444
+ pushFinding({
102445
+ code: "gsap_css_transform_conflict",
102446
+ severity: "warning",
102447
+ 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.`,
102448
+ selector: sel,
102449
+ 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.`,
102450
+ snippet: truncateSnippet(raw2)
102451
+ });
102452
+ }
102453
+ }
102454
+ }
102455
+ }
102382
102456
  const errorCount = findings.filter((finding) => finding.severity === "error").length;
102383
102457
  const warningCount = findings.length - errorCount;
102384
102458
  return {
@@ -102522,6 +102596,7 @@ function extractGsapWindows(script) {
102522
102596
  end: animation.position + meta.effectiveDuration,
102523
102597
  properties: meta.properties.length > 0 ? meta.properties : Object.keys(animation.properties),
102524
102598
  overwriteAuto: meta.overwriteAuto,
102599
+ method: match2[1] ?? "to",
102525
102600
  raw: raw2
102526
102601
  });
102527
102602
  }
@@ -106960,7 +107035,8 @@ function parseRenderOptions(body) {
106960
107035
  const debug6 = body.debug === true;
106961
107036
  const outputPath = typeof body.outputPath === "string" && body.outputPath.trim().length > 0 ? body.outputPath : typeof body.output === "string" && body.output.trim().length > 0 ? body.output : null;
106962
107037
  const entryFile = typeof body.entryFile === "string" && body.entryFile.trim().length > 0 ? body.entryFile.trim() : void 0;
106963
- return { outputPath, fps, quality, workers, useGpu, debug: debug6, entryFile };
107038
+ const format3 = ["mp4", "webm"].includes(body.format) ? body.format : void 0;
107039
+ return { outputPath, fps, quality, workers, useGpu, debug: debug6, entryFile, format: format3 };
106964
107040
  }
106965
107041
  async function prepareRenderBody(body) {
106966
107042
  const options = parseRenderOptions(body);
@@ -107128,6 +107204,7 @@ function createRenderHandlers(options = {}) {
107128
107204
  const job = createRenderJob({
107129
107205
  fps: input2.fps,
107130
107206
  quality: input2.quality,
107207
+ format: input2.format,
107131
107208
  workers: input2.workers,
107132
107209
  useGpu: input2.useGpu,
107133
107210
  debug: input2.debug,
@@ -107231,6 +107308,7 @@ function createRenderHandlers(options = {}) {
107231
107308
  const job = createRenderJob({
107232
107309
  fps: input2.fps,
107233
107310
  quality: input2.quality,
107311
+ format: input2.format,
107234
107312
  workers: input2.workers,
107235
107313
  useGpu: input2.useGpu,
107236
107314
  debug: input2.debug,