@hyperframes/producer 0.4.13 → 0.4.15-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -99570,6 +99570,110 @@ var coreRules = [
99570
99570
  ];
99571
99571
 
99572
99572
  // ../core/src/lint/rules/media.ts
99573
+ function escapeRegExp(value) {
99574
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
99575
+ }
99576
+ function selectorTargetsManagedMedia(selector, mediaIds) {
99577
+ const normalized = selector.trim();
99578
+ if (!normalized) return false;
99579
+ if (/\b(video|audio)\b/i.test(normalized)) return true;
99580
+ for (const mediaId of mediaIds) {
99581
+ if (normalized.includes(`#${mediaId}`) || normalized.includes(`[id="${mediaId}"]`) || normalized.includes(`[id='${mediaId}']`)) {
99582
+ return true;
99583
+ }
99584
+ }
99585
+ return false;
99586
+ }
99587
+ function findImperativeMediaControlFindings(ctx) {
99588
+ const findings = [];
99589
+ const managedMediaIds = new Set(
99590
+ ctx.tags.filter((tag) => tag.name === "video" || tag.name === "audio").map((tag) => readAttr(tag.raw, "id")).filter((id) => Boolean(id))
99591
+ );
99592
+ if (managedMediaIds.size === 0 || ctx.scripts.length === 0) return findings;
99593
+ for (const script of ctx.scripts) {
99594
+ const mediaVars = /* @__PURE__ */ new Map();
99595
+ const assignmentPatterns = [
99596
+ /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*(?:document|window\.document)\.getElementById\(\s*["']([^"']+)["']\s*\)/g,
99597
+ /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*(?:document|window\.document)\.querySelector\(\s*["']([^"']+)["']\s*\)/g
99598
+ ];
99599
+ for (const pattern of assignmentPatterns) {
99600
+ let match2;
99601
+ while ((match2 = pattern.exec(script.content)) !== null) {
99602
+ const variableName = match2[1];
99603
+ const target = match2[2];
99604
+ if (!variableName || !target) continue;
99605
+ if (managedMediaIds.has(target) || selectorTargetsManagedMedia(target, managedMediaIds)) {
99606
+ mediaVars.set(variableName, managedMediaIds.has(target) ? target : void 0);
99607
+ }
99608
+ }
99609
+ }
99610
+ const directIdPatterns = [
99611
+ {
99612
+ pattern: /\b(?:document|window\.document)\.getElementById\(\s*["']([^"']+)["']\s*\)\.play\s*\(/g,
99613
+ kind: "play()"
99614
+ },
99615
+ {
99616
+ pattern: /\b(?:document|window\.document)\.getElementById\(\s*["']([^"']+)["']\s*\)\.pause\s*\(/g,
99617
+ kind: "pause()"
99618
+ },
99619
+ {
99620
+ pattern: /\b(?:document|window\.document)\.getElementById\(\s*["']([^"']+)["']\s*\)\.currentTime\s*=/g,
99621
+ kind: "currentTime"
99622
+ },
99623
+ {
99624
+ pattern: /\b(?:document|window\.document)\.querySelector\(\s*["']([^"']+)["']\s*\)\.play\s*\(/g,
99625
+ kind: "play()"
99626
+ },
99627
+ {
99628
+ pattern: /\b(?:document|window\.document)\.querySelector\(\s*["']([^"']+)["']\s*\)\.pause\s*\(/g,
99629
+ kind: "pause()"
99630
+ },
99631
+ {
99632
+ pattern: /\b(?:document|window\.document)\.querySelector\(\s*["']([^"']+)["']\s*\)\.currentTime\s*=/g,
99633
+ kind: "currentTime"
99634
+ }
99635
+ ];
99636
+ for (const { pattern, kind } of directIdPatterns) {
99637
+ let match2;
99638
+ while ((match2 = pattern.exec(script.content)) !== null) {
99639
+ const target = match2[1];
99640
+ if (!target) continue;
99641
+ const elementId = managedMediaIds.has(target) ? target : selectorTargetsManagedMedia(target, managedMediaIds) ? void 0 : null;
99642
+ if (elementId === null) continue;
99643
+ findings.push({
99644
+ code: "imperative_media_control",
99645
+ severity: "error",
99646
+ message: `Inline <script> imperatively controls managed media via ${kind}. HyperFrames must own media play/pause/seek to keep preview, timeline, and renders deterministic.`,
99647
+ elementId: elementId || void 0,
99648
+ fixHint: "Remove imperative media play/pause/currentTime control. Express timing with data-start/data-duration and media offsets like data-media-start or data-playback-start instead.",
99649
+ snippet: truncateSnippet(match2[0])
99650
+ });
99651
+ }
99652
+ }
99653
+ for (const [variableName, elementId] of mediaVars) {
99654
+ const escapedVar = escapeRegExp(variableName);
99655
+ const variablePatterns = [
99656
+ { pattern: new RegExp(`\\b${escapedVar}\\.play\\s*\\(`, "g"), kind: "play()" },
99657
+ { pattern: new RegExp(`\\b${escapedVar}\\.pause\\s*\\(`, "g"), kind: "pause()" },
99658
+ { pattern: new RegExp(`\\b${escapedVar}\\.currentTime\\s*=`, "g"), kind: "currentTime" }
99659
+ ];
99660
+ for (const { pattern, kind } of variablePatterns) {
99661
+ let match2;
99662
+ while ((match2 = pattern.exec(script.content)) !== null) {
99663
+ findings.push({
99664
+ code: "imperative_media_control",
99665
+ severity: "error",
99666
+ message: `Inline <script> imperatively controls managed media via ${kind}. HyperFrames must own media play/pause/seek to keep preview, timeline, and renders deterministic.`,
99667
+ elementId,
99668
+ fixHint: "Remove imperative media play/pause/currentTime control. Express timing with data-start/data-duration and media offsets like data-media-start or data-playback-start instead.",
99669
+ snippet: truncateSnippet(match2[0])
99670
+ });
99671
+ }
99672
+ }
99673
+ }
99674
+ }
99675
+ return findings;
99676
+ }
99573
99677
  var mediaRules = [
99574
99678
  // duplicate_media_id + duplicate_media_discovery_risk
99575
99679
  ({ tags }) => {
@@ -99792,7 +99896,9 @@ var mediaRules = [
99792
99896
  }
99793
99897
  }
99794
99898
  return findings;
99795
- }
99899
+ },
99900
+ // imperative_media_control
99901
+ findImperativeMediaControlFindings
99796
99902
  ];
99797
99903
 
99798
99904
  // ../core/src/lint/rules/gsap.ts
@@ -110243,8 +110349,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110243
110349
  )
110244
110350
  });
110245
110351
  }
110246
- for (let layerIdx = 0; layerIdx < layers.length; layerIdx++) {
110247
- const layer = layers[layerIdx];
110352
+ for (const [layerIdx, layer] of layers.entries()) {
110248
110353
  if (layer.type === "hdr") {
110249
110354
  const before2 = shouldLog ? countNonZeroRgb482(canvas) : 0;
110250
110355
  const isHdrImage = nativeHdrImageIds.has(layer.element.id);