···
3
+
import { mkdir, readdir, rm } from "node:fs/promises";
4
+
import { join } from "node:path";
5
+
import { $ } from "bun";
7
+
const OUTPUT_DIR = join(import.meta.dir, "../output");
8
+
const VIS_DIR = join(import.meta.dir, "../vis");
10
+
console.log("🎨 Generating all visualizations...\n");
12
+
// Clean output directory
13
+
await rm(OUTPUT_DIR, { recursive: true, force: true });
14
+
await mkdir(OUTPUT_DIR, { recursive: true });
16
+
// Auto-detect days from vis directory
17
+
const entries = await readdir(VIS_DIR, { withFileTypes: true });
18
+
const days = entries
19
+
.filter((entry) => entry.isDirectory() && /^\d{2}$/.test(entry.name))
20
+
.map((entry) => entry.name)
23
+
// Generate each day's visualization
24
+
for (const day of days) {
25
+
console.log(`📊 Day ${day}...`);
26
+
const dayDir = join(VIS_DIR, day);
27
+
const generateScript = join(dayDir, "generate.ts");
29
+
// Run the generator
30
+
await $`cd ${dayDir} && bun ${generateScript}`;
32
+
// Copy the output to the output directory
33
+
const outputDayDir = join(OUTPUT_DIR, day);
34
+
await mkdir(outputDayDir, { recursive: true });
35
+
await $`cp ${join(dayDir, "index.html")} ${outputDayDir}/index.html`;
37
+
console.log(` ✓ Generated ${day}`);
40
+
// Generate index page
41
+
console.log("\n📄 Generating index page...");
44
+
const dayInfo: Record<string, { title: string; description: string }> = {
46
+
title: "Paper Removal",
48
+
"Watch papers being removed layer by layer from a grid. Papers with fewer than 4 neighbors (including diagonals) are accessible and removed each iteration.",
52
+
const dayCards = days
54
+
const info = dayInfo[day];
55
+
if (!info) return "";
58
+
<a href="${day}/index.html" class="day-item">
59
+
<span class="day-number">Day ${parseInt(day, 10)}:</span>
60
+
<span class="day-title">${info.title}</span>
61
+
<span class="stars"> **</span>
63
+
<div class="day-description">${info.description}</div>
68
+
const indexHtml = `<!DOCTYPE html>
71
+
<meta charset="UTF-8">
72
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
73
+
<title>Advent of Code 2025 - Visualizations</title>
76
+
background: #1e1e2e;
78
+
font-family: "Source Code Pro", monospace;
84
+
text-decoration: none;
89
+
background-color: #181825 !important;
93
+
font-weight: normal;
96
+
white-space: nowrap;
100
+
display: inline-block;
102
+
padding-right: 1em;
106
+
text-shadow: 0 0 2px #a6e3a1, 0 0 5px #a6e3a1;
114
+
margin-bottom: 2em;
119
+
margin-bottom: 1em;
122
+
list-style-type: none;
130
+
.day-item:hover, .day-item:focus {
131
+
background-color: #181825 !important;
144
+
padding-left: 2.5em;
149
+
text-align: center;
155
+
<h1><span>Advent of Code</span> 2025 - Visualizations</h1>
160
+
<h2>Interactive Problem Visualizations</h2>
161
+
<ul class="days-list">
169
+
Made with ♥ by <a href="https://dunkirk.sh">Kieran Klukas</a>
171
+
<a href="https://adventofcode.com/2025">[Return to Advent of Code]</a>
176
+
await Bun.write(join(OUTPUT_DIR, "index.html"), indexHtml);
178
+
console.log("\n✨ All visualizations generated successfully!");
179
+
console.log(`📁 Output directory: ${OUTPUT_DIR}`);
180
+
console.log(`🌐 Open ${join(OUTPUT_DIR, "index.html")} to view\n`);