Files
roboco/motion/compositions/release-announcement/square.html
T
Renn F 9124c5836d fix(video): reclaim outDir on createRenderJob throw + hide empty 4th highlight
Final whole-branch review (Opus) triaged two FIX items from the SDD nits
ledger; the rest ship as-is.

- render.js: a synchronous throw from createRenderJob (post-mkdtemp, not
  awaited) left an empty outDir on disk — the outer catch only reclaimed
  extractDir. Reclaim outDir too when it exists, and correct the stale
  comment that claimed the out dir was never created.
- {vertical,square}.html: the 4th highlights <li> lived in the DOM hidden
  only by JS, so a no-JS / failed-script render would show an empty bullet.
  Start it style="display:none" and reveal on populate, so an unscripted
  render shows nothing instead.

Vitest smoke (release-announcement.test.js) 4/4 green; render.js syntax
checked. Python suite untouched by this fix (JS/HTML only).
2026-07-06 02:38:10 +02:00

79 lines
4.1 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="en" data-composition-id="release-announcement" data-composition-duration="10" data-fps="30">
<head>
<meta charset="utf-8" />
<title>Release Announcement — square (1080×1080)</title>
<link rel="stylesheet" href="theme.css" />
<script src="props.js"></script>
</head>
<body>
<div id="stage" data-composition-id="release-announcement" data-width="1080" data-height="1080" data-start="0" data-duration="10" data-fps="30">
<!-- Scan line: thin hairline + travelling accent marker. Square cut
uses a tighter scan top (72) than the vertical cut (104). -->
<div id="scan" class="scan clip" data-start="0" data-duration="10" data-track-index="0" style="top: 72px;">
<div class="scan__marker"></div>
</div>
<!-- Content anchored in the lower two-thirds, left-aligned. Square cut
uses a tighter bottom pad (72) than the vertical cut (148). -->
<div class="content" style="--content-bottom: 72px;">
<div id="kicker" class="kicker clip" data-start="0" data-duration="10" data-track-index="1">New release</div>
<h1 id="headline" class="headline clip" data-start="0.267" data-duration="9.733" data-track-index="2">v0.19.0</h1>
<p id="script" class="script clip" data-start="0.8" data-duration="9.2" data-track-index="3">Ship day. Faster renders, sharper docs, one less thing to babysit.</p>
<ul id="highlights" class="highlights clip" data-start="1.667" data-duration="8.333" data-track-index="4">
<li class="highlights__item"><span class="highlights__tick"></span><span class="highlights__text">Fable-mode adopted fleet-wide</span></li>
<li class="highlights__item"><span class="highlights__tick"></span><span class="highlights__text">FE/UX-UI design bar shipped</span></li>
<li class="highlights__item"><span class="highlights__tick"></span><span class="highlights__text">Feature spotlight goes live on X</span></li>
<li class="highlights__item" style="display:none"><span class="highlights__tick"></span><span class="highlights__text"></span></li>
</ul>
</div>
<div id="outro" class="outro clip" data-start="7.667" data-duration="2.333" data-track-index="5">roboco.tech</div>
</div>
<script>
// Register the composition timeline metadata. Motion is driven by CSS
// keyframes (no GSAP — the render is offline, no CDN), but HyperFrames
// requires the registry entry to consider the composition valid.
window.__timelines = window.__timelines || {};
window.__timelines["release-announcement"] = {
id: "release-announcement",
duration: 10,
fps: 30,
animations: []
};
// Read sidecar-supplied props (props.js is overwritten at render time)
// and populate the DOM. Defensive: a missing prop leaves the placeholder
// text intact rather than throwing — a missing prop never crashes a render.
(function () {
var props = (window.__PROPS__ && typeof window.__PROPS__ === "object") ? window.__PROPS__ : {};
var version = props.version ? String(props.version) : "";
if (version && !version.startsWith("v")) version = "v" + version;
if (version) {
var headline = document.getElementById("headline");
if (headline) headline.textContent = version;
}
if (typeof props.script === "string" && props.script) {
var scriptEl = document.getElementById("script");
if (scriptEl) scriptEl.textContent = props.script;
}
var highlights = Array.isArray(props.highlights) ? props.highlights.slice(0, 4) : [];
var items = document.querySelectorAll(".highlights__item");
for (var i = 0; i < items.length; i++) {
var textEl = items[i].querySelector(".highlights__text");
if (!textEl) continue;
if (i < highlights.length && highlights[i]) {
textEl.textContent = String(highlights[i]);
items[i].style.display = "";
} else {
items[i].style.display = "none";
}
}
})();
</script>
</body>
</html>