hyperframes 0.8.68 → 0.8.70

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.
Files changed (30) hide show
  1. package/dist/cli.js +127 -68
  2. package/dist/commands/layout-audit.browser.js +36 -4
  3. package/dist/fontLocalizeCli.js +25 -10
  4. package/dist/hyperframe-runtime.js +37 -37
  5. package/dist/hyperframe.manifest.json +1 -1
  6. package/dist/hyperframe.runtime.iife.js +37 -37
  7. package/dist/hyperframes-player.global.js +1 -1
  8. package/dist/renderSetupWorker.js +7 -7
  9. package/dist/skills/hyperframes/scripts/lib/frame-packets-core.mjs +5 -23
  10. package/dist/skills/media-use/audio/references/tts-to-captions.md +11 -2
  11. package/dist/skills/media-use/audio/references/tts.md +84 -6
  12. package/dist/skills/media-use/audio/scripts/audio.mjs +10 -3
  13. package/dist/skills/media-use/audio/scripts/gemini-pipeline.test.mjs +113 -0
  14. package/dist/skills/media-use/audio/scripts/lib/bgm-volume.mjs +4 -0
  15. package/dist/skills/media-use/audio/scripts/lib/bgm.mjs +2 -6
  16. package/dist/skills/media-use/audio/scripts/lib/gemini-auth.mjs +43 -0
  17. package/dist/skills/media-use/audio/scripts/lib/gemini-auth.py +52 -0
  18. package/dist/skills/media-use/audio/scripts/lib/gemini-auth.test.mjs +86 -0
  19. package/dist/skills/media-use/audio/scripts/lib/gemini-auth_test.py +90 -0
  20. package/dist/skills/media-use/audio/scripts/lib/gemini-tts.mjs +122 -0
  21. package/dist/skills/media-use/audio/scripts/lib/gemini-tts.test.mjs +243 -0
  22. package/dist/skills/media-use/audio/scripts/lib/tts.mjs +13 -2
  23. package/dist/skills/media-use/references/audio.md +2 -1
  24. package/dist/skills/media-use/scripts/compatibility.test.mjs +68 -1
  25. package/dist/studio/assets/{hyperframes-player-RYzFlKye.js → hyperframes-player-CYdwxTwz.js} +1 -1
  26. package/dist/studio/assets/{index-CsnhFJIv.js → index-BPafHV3q.js} +1 -1
  27. package/dist/studio/assets/{index-C8-wAsq3.js → index-D7hgjzBq.js} +1 -1
  28. package/dist/studio/assets/{index-P0Rwat37.js → index-Egnc_kWw.js} +4 -4
  29. package/dist/studio/index.html +1 -1
  30. package/package.json +1 -1
@@ -27,6 +27,16 @@
27
27
  return Math.round(value * 100) / 100;
28
28
  }
29
29
 
30
+ function horizontalOverflow(subject, container, tolerance) {
31
+ if (subject.width <= container.width + tolerance) return null;
32
+ const overflow = overflowFor(subject, container, tolerance);
33
+ if (!overflow) return null;
34
+ const horizontal = {};
35
+ if (overflow.left != null) horizontal.left = overflow.left;
36
+ if (overflow.right != null) horizontal.right = overflow.right;
37
+ return Object.keys(horizontal).length > 0 ? horizontal : null;
38
+ }
39
+
30
40
  function overflowFor(subject, container, tolerance, vTolerance) {
31
41
  // Horizontal axis uses `tolerance`; vertical axis uses `vTolerance` (defaults to the same).
32
42
  // A separate vertical tolerance lets text overflow checks absorb glyph ink that exceeds a
@@ -550,20 +560,40 @@
550
560
  return issues;
551
561
  }
552
562
 
563
+ function isNowrapTextChild(child) {
564
+ if (!isVisibleElement(child) || hasAllowOverflowFlag(child)) return false;
565
+ if (getComputedStyle(child).whiteSpace !== "nowrap") return false;
566
+ return (child.textContent || "").trim().length > 0;
567
+ }
568
+
569
+ function hasNowrapTextChild(element) {
570
+ return Array.from(element.children).some(isNowrapTextChild);
571
+ }
572
+
553
573
  function containerOverflowIssues(root, time, tolerance) {
554
574
  const issues = [];
555
575
  const containers = Array.from(root.querySelectorAll("*")).filter((element) => {
556
576
  if (!isVisibleElement(element) || hasAllowOverflowFlag(element)) return false;
557
577
  const style = getComputedStyle(element);
558
- return clipsOverflow(style) || element.hasAttribute("data-layout-boundary");
578
+ return (
579
+ clipsOverflow(style) ||
580
+ element.hasAttribute("data-layout-boundary") ||
581
+ hasNowrapTextChild(element)
582
+ );
559
583
  });
560
584
 
561
585
  for (const container of containers) {
586
+ const style = getComputedStyle(container);
587
+ const checksEveryChild =
588
+ clipsOverflow(style) || container.hasAttribute("data-layout-boundary");
562
589
  const containerRect = toRect(container.getBoundingClientRect());
563
590
  for (const child of Array.from(container.children)) {
564
591
  if (!isVisibleElement(child) || hasAllowOverflowFlag(child)) continue;
592
+ if (!checksEveryChild && !isNowrapTextChild(child)) continue;
565
593
  const childRect = toRect(child.getBoundingClientRect());
566
- const overflow = overflowFor(childRect, containerRect, tolerance);
594
+ const overflow = checksEveryChild
595
+ ? overflowFor(childRect, containerRect, tolerance)
596
+ : horizontalOverflow(childRect, containerRect, tolerance);
567
597
  if (!overflow) continue;
568
598
  issues.push({
569
599
  code: "container_overflow",
@@ -571,7 +601,9 @@
571
601
  time,
572
602
  selector: selectorFor(child),
573
603
  containerSelector: selectorFor(container),
574
- message: "Element extends outside a clipping layout container.",
604
+ message: checksEveryChild
605
+ ? "Element extends outside a clipping layout container."
606
+ : "Nowrap text is wider than its container.",
575
607
  rect: childRect,
576
608
  containerRect,
577
609
  overflow,
@@ -911,7 +943,7 @@
911
943
  }
912
944
 
913
945
  function hasAllowOcclusionFlag(element) {
914
- return !!element.closest("[data-layout-allow-occlusion]");
946
+ return element.hasAttribute("data-layout-allow-occlusion");
915
947
  }
916
948
 
917
949
  // A foreign element is one painted independently of the text — not the text
@@ -72911,17 +72911,17 @@ function truncateSnippet(value, maxLength = 220) {
72911
72911
  return `${normalized2.slice(0, maxLength - 3)}...`;
72912
72912
  }
72913
72913
  function normalized(source) {
72914
- let text = "";
72914
+ const chars = [];
72915
72915
  const offsets = [];
72916
+ let lastWasSpace = false;
72916
72917
  for (let i = 0; i < source.length; i++) {
72917
- const char = source[i];
72918
- if (/\s/.test(char)) {
72919
- if (text.endsWith(" ")) continue;
72920
- text += " ";
72921
- } else text += char;
72918
+ const isSpace = /\s/.test(source[i]);
72919
+ if (isSpace && lastWasSpace) continue;
72920
+ chars.push(isSpace ? " " : source[i]);
72922
72921
  offsets.push(i);
72922
+ lastWasSpace = isSpace;
72923
72923
  }
72924
- return { text, offsets };
72924
+ return { text: chars.join(""), offsets };
72925
72925
  }
72926
72926
  function createSourceLocator(source) {
72927
72927
  const tags = parseHtmlStructure(source).tags;
@@ -79430,6 +79430,15 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
79430
79430
  `FFmpeg exited successfully but produced no frames (start=${startTime}, duration=${duration})`
79431
79431
  );
79432
79432
  }
79433
+ if (framePaths.size > 0 && duration > 0 && !options.finalFrameOnly) {
79434
+ const expectedAtFps = extractionFrameCountForDuration(duration, normalizedFps, metadata.isVFR);
79435
+ if (expectedAtFps > 0 && framePaths.size <= expectedAtFps * 0.6) {
79436
+ const correctedDuration = startTime + framePaths.size / fps;
79437
+ if (correctedDuration < metadata.videoStreamDurationSeconds) {
79438
+ metadata.videoStreamDurationSeconds = correctedDuration;
79439
+ }
79440
+ }
79441
+ }
79433
79442
  return {
79434
79443
  videoId,
79435
79444
  srcPath: videoPath,
@@ -94205,6 +94214,12 @@ function resolveFontFetchRetryPolicy(configured) {
94205
94214
  )
94206
94215
  };
94207
94216
  }
94217
+ function placeAfterEveryStylesheet(document2, head, styleEl) {
94218
+ const stylesheets = document2.querySelectorAll("style, link[rel~=stylesheet]");
94219
+ const lastStylesheet = stylesheets[stylesheets.length - 1];
94220
+ if (lastStylesheet) lastStylesheet.after(styleEl);
94221
+ else head.appendChild(styleEl);
94222
+ }
94208
94223
  async function injectDeterministicFontFaces(html, options = {}) {
94209
94224
  const failClosedFontFetch = options.failClosedFontFetch === true;
94210
94225
  const fetchImpl = options.fetchImpl ?? fetch;
@@ -94255,7 +94270,7 @@ async function injectDeterministicFontFaces(html, options = {}) {
94255
94270
  const styleEl = document2.createElement("style");
94256
94271
  styleEl.setAttribute("data-hyperframes-deterministic-fonts", "true");
94257
94272
  styleEl.textContent = css;
94258
- head.insertBefore(styleEl, head.firstChild);
94273
+ placeAfterEveryStylesheet(document2, head, styleEl);
94259
94274
  defaultLogger.info(
94260
94275
  `[Compiler] Injected deterministic @font-face rules for ${pendingFamilies.size - unresolved.length} requested font families`
94261
94276
  );
@@ -103722,8 +103737,8 @@ async function runFontLocalize(io, localize) {
103722
103737
  }
103723
103738
 
103724
103739
  // src/version.ts
103725
- var VERSION = true ? "0.8.68" : "0.0.0-dev";
103726
- var PRODUCER_VERSION = true ? "0.8.68" : "0.0.0-dev";
103740
+ var VERSION = true ? "0.8.70" : "0.0.0-dev";
103741
+ var PRODUCER_VERSION = true ? "0.8.70" : "0.0.0-dev";
103727
103742
 
103728
103743
  // src/fontLocalizeCli.ts
103729
103744
  async function readStdin() {