diff --git a/scripts/build-dist.mjs b/scripts/build-dist.mjs index c19d684d..1aa36a6f 100644 --- a/scripts/build-dist.mjs +++ b/scripts/build-dist.mjs @@ -2,6 +2,7 @@ import fs from 'node:fs'; import path from 'node:path'; import { execSync } from 'node:child_process'; import crypto from 'node:crypto'; +import { buildHashState } from './hash-dist.mjs'; const DIST = 'dist'; const FILES_TO_COPY = [ @@ -154,6 +155,38 @@ function rewriteEntryHtmlAssetPaths(manifest) { } } +function injectVersionInfo() { + console.log('Injecting version hash and date...'); + try { + const hashState = buildHashState(DIST); + const hash = hashState.combined; + const date = new Date().toISOString().split('T')[0]; + + const indexHtmlPath = path.join(DIST, 'index.html'); + if (fs.existsSync(indexHtmlPath)) { + let content = fs.readFileSync(indexHtmlPath, 'utf8'); + + const versionHtml = ` +
+ v: ${hash.slice(0, 8)} • ${date} +
`; + + // Fallback search if whitespace differs + const taglineRegex = /(seed\. zap\. subscribe\.\s*<\/h2>)/; + if (taglineRegex.test(content)) { + content = content.replace(taglineRegex, '$1' + versionHtml); + fs.writeFileSync(indexHtmlPath, content); + console.log(`Injected version: ${hash.slice(0, 8)} • ${date}`); + } else { + console.warn('Could not find tagline to inject version info.'); + } + } + } catch (error) { + console.error('Failed to inject version info:', error); + // Continue even if injection fails, as it's not critical for functionality + } +} + function main() { console.log('Validating service worker compatibility guard...'); try { @@ -209,6 +242,8 @@ function main() { console.log('Rewriting HTML entry points with hashed assets...'); rewriteEntryHtmlAssetPaths(manifest); + injectVersionInfo(); + console.log('Build complete.'); } diff --git a/scripts/hash-dist.mjs b/scripts/hash-dist.mjs index 8637c776..dc41b53e 100644 --- a/scripts/hash-dist.mjs +++ b/scripts/hash-dist.mjs @@ -2,6 +2,7 @@ import fs from 'node:fs'; import path from 'node:path'; import crypto from 'node:crypto'; +import { fileURLToPath } from 'node:url'; function parseArgs(argv) { const args = { @@ -72,7 +73,7 @@ function hashBuffer(buffer) { return crypto.createHash('sha256').update(buffer).digest('hex'); } -function buildHashState(distDir) { +export function buildHashState(distDir) { const resolvedDistDir = path.resolve(distDir); if (!fs.existsSync(resolvedDistDir)) { throw new Error(`Dist directory does not exist: ${resolvedDistDir}`); @@ -112,4 +113,6 @@ function main() { console.log(serialized); } -main(); +if (process.argv[1] === fileURLToPath(import.meta.url)) { + main(); +} diff --git a/verification.png b/verification.png new file mode 100644 index 00000000..fda37f88 Binary files /dev/null and b/verification.png differ diff --git a/verify_version.py b/verify_version.py new file mode 100644 index 00000000..0130aaff --- /dev/null +++ b/verify_version.py @@ -0,0 +1,29 @@ +from playwright.sync_api import sync_playwright + +def run(): + with sync_playwright() as p: + browser = p.chromium.launch() + page = browser.new_page() + page.goto("http://localhost:3000") + + # Locate the tagline + tagline = page.get_by_text("seed. zap. subscribe.") + + # Locate the version info which should be nearby + # The tagline is an h2 inside a div. + container = tagline.locator("..") + + # Wait for fade-in to settle or just force visibility? + # The container has "fade-in" class. It might take time. + # I'll wait for the version text to be visible. + version_locator = container.locator("div.text-xs") + version_locator.wait_for() + + print("Version text found:", version_locator.inner_text()) + + # Screenshot the container + container.screenshot(path="verification.png") + browser.close() + +if __name__ == "__main__": + run()