From 3dc5f9176948c918b8f62a47846fadd05bb2e1fb Mon Sep 17 00:00:00 2001 From: tshmieldev Date: Mon, 21 Sep 2026 15:17:15 +0200 Subject: [PATCH] fix: the promo recorder runs from a fresh install From the review on #9. - playwright was imported but not declared, so `bun promo/record.mjs` failed after a fresh install. It is a dev dependency now; the browser is still a separate one-off download, noted at the top of the script. - The page's file URL is built with pathToFileURL, so a folder named with #, ? or % stays a path. - The PROMO_DIR override is gone: it existed only to run the script from outside the repo while playwright was missing. --- bun.lock | 5 +++++ package.json | 1 + promo/record.mjs | 18 +++++++++++------- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/bun.lock b/bun.lock index 9a8e697..1a56d58 100644 --- a/bun.lock +++ b/bun.lock @@ -13,6 +13,7 @@ "@types/node": "^22.0.0", "esbuild": "^0.25.0", "jsdom": "^26.0.0", + "playwright": "^1.63.0", "prettier": "^3.6.0", "typescript": "^5.9.0", "vitest": "^3.2.0", @@ -244,6 +245,10 @@ "picomatch": ["picomatch@4.0.7", "", {}, "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA=="], + "playwright": ["playwright@1.63.0", "", { "dependencies": { "playwright-core": "1.63.0" }, "bin": { "playwright": "cli.js" } }, "sha512-+7ziBLidS4NaNCdt57SUDT+wYmmd5fmiQejUic/kb+YsYSCPyOOE9sebzMjNmQrsnNpDJqd4WHvV/8lfKfUDUg=="], + + "playwright-core": ["playwright-core@1.63.0", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-rYCsBF/M5HjUch52bbtVONEFjv6Xu8sm8h72dNlR5bzIE1fvC/bxgspzkjSfU+MweEMmPM8KJebG6nnyxo5mCg=="], + "postcss": ["postcss@8.5.28", "", { "dependencies": { "nanoid": "^3.3.18", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A=="], "preact": ["preact@10.29.8", "", { "peerDependencies": { "preact-render-to-string": ">=5" }, "optionalPeers": ["preact-render-to-string"] }, "sha512-ej2aVZ+vZ8WO7tvlQWRM9N63A0KzF9q4mWJfDUHgYaIofWY9hu74QdnQrjoPMmZi2/nZ5gN0bJCQF49xQqx09Q=="], diff --git a/package.json b/package.json index 9567948..744e96a 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "@types/node": "^22.0.0", "esbuild": "^0.25.0", "jsdom": "^26.0.0", + "playwright": "^1.63.0", "prettier": "^3.6.0", "typescript": "^5.9.0", "vitest": "^3.2.0" diff --git a/promo/record.mjs b/promo/record.mjs index a7bc81e..98d38b4 100644 --- a/promo/record.mjs +++ b/promo/record.mjs @@ -1,14 +1,15 @@ -// Renders promo/sliders.html to an MP4, one frame at a time, so the result is -// smooth whatever the machine: `bun promo/record.mjs [name]` renders promo/.html -// to promo/sharp-.mp4 (needs playwright and ffmpeg). Default name: simple. -// A square cut: `bun promo/record.mjs list-square 1080 1080 1`. +// Renders a promo page to an MP4, one frame at a time, so the result is smooth +// whatever the machine: `bun promo/record.mjs [name]` renders promo/.html to +// promo/sharp-.mp4. Default name: simple. A square cut: +// `bun promo/record.mjs list-square 1080 1080 1`. +// Needs ffmpeg, and a browser for playwright: `bunx playwright install chromium`. import { chromium } from 'playwright'; import { mkdir, rm } from 'node:fs/promises'; import { execFileSync } from 'node:child_process'; -import { fileURLToPath } from 'node:url'; +import { fileURLToPath, pathToFileURL } from 'node:url'; import path from 'node:path'; -const here = process.env.PROMO_DIR ?? path.dirname(fileURLToPath(import.meta.url)); +const here = path.dirname(fileURLToPath(import.meta.url)); const frames = path.join(here, '.frames'); const FPS = 30; const name = process.argv[2] ?? 'simple'; @@ -22,7 +23,10 @@ await mkdir(frames, { recursive: true }); const browser = await chromium.launch(); const page = await browser.newPage({ viewport: { width, height }, deviceScaleFactor: scale }); -await page.goto(`file://${path.join(here, `${name}.html`)}?still`); +// Built as a URL, not a string: a folder named with #, ? or % stays a path. +const url = pathToFileURL(path.join(here, `${name}.html`)); +url.searchParams.set('still', ''); +await page.goto(url.href); await page.evaluate(() => document.fonts.ready); const duration = await page.evaluate(() => window.DURATION); const total = Math.round(duration * FPS);