From 35197e9d466b5eca56137fceccd0d061cf3bbb1c Mon Sep 17 00:00:00 2001
From: clover caruso
Date: Tue, 5 May 2026 00:34:48 -0700
Subject: [PATCH] feat: random stuff on site and bug fixes too
---
framework/font.ts | 51 ++++++++++++++++++++++++++++++++++++--
framework/generate.ts | 2 +-
framework/watch.ts | 6 +++--
package-lock.json | 16 ++++++------
package.json | 2 +-
src/file-viewer/backend.ts | 6 ++---
src/pages/dream.mdo | 42 +++++++++++++++++++++++++++++++
src/pages/index.marko | 15 ++++++-----
src/pages/subscribe.marko | 4 +--
9 files changed, 118 insertions(+), 26 deletions(-)
create mode 100644 src/pages/dream.mdo
diff --git a/framework/font.ts b/framework/font.ts
index 8814b1aab17ac32dcb01165f2d91c0a5d9a48f66..c3935c292b4a7d7648ea0768b56470810f117189 100644
--- a/framework/font.ts
+++ b/framework/font.ts
@@ -1,4 +1,4 @@
-export async function buildFonts(p: progress.Ref, fonts: sg.Font[]) {
+export async function buildFonts(p: progress.Ref, fonts: sg.Font[], base: string) {
if (fonts.length === 0) return;
using node = p.start("build fonts");
function getArgs(vars: sg.FontVars) {
@@ -22,7 +22,14 @@ export async function buildFonts(p: progress.Ref, fonts: sg.Font[]) {
await Promise.all(fonts.map((font) =>
incr.work(node, async (io, font) => {
using node = io.start(font.name);
- const baseFile = await fetchFont(node, font.name, font.sources);
+ let baseFile: string;
+ try {
+ baseFile = await fetchFont(node, font.name, font.sources);
+ } catch (err) {
+ using _ = node.start("fetch fallback");
+ await fetchProductionFontFiles(node, io, font, base);
+ return;
+ }
await using baseBuffer = async.deferred(fs.readFile(baseFile));
await Promise.all(font.subsets.map(async (subset) => {
const args = getArgs(subset.vars ?? {});
@@ -66,6 +73,44 @@ export async function buildFonts(p: progress.Ref, fonts: sg.Font[]) {
));
}
+async function fetchProductionFontFiles(
+ ref: progress.Ref,
+ io: incr.Io,
+ font: sg.Font,
+ base: string,
+) {
+ const fetchPromises = font.subsets.flatMap((subset) => {
+ return ["woff2", "ttf", "eot"].map(async (ext) => {
+ const assetPath = subset.asset.replace("[ext]", ext);
+ const cacheDir = path.join(os.tmpdir(), "sitegen-fonts", font.name);
+ fs.mkdirSync(cacheDir);
+ const cacheName = path.join(cacheDir, assetPath.replace(/[\/\\]/g, "_"));
+
+ if (!fs.existsSync(cacheName)) {
+ const url = new URL(assetPath, base).href;
+ try {
+ using _ = ref.start("fetch: " + assetPath);
+ const response = await fetch(url);
+ if (response.ok) {
+ await fs.writeMkdir(cacheName, new Uint8Array(await response.arrayBuffer()));
+ } else {
+ throw new Error(`Fetching fallback from ${url} failed: ${response.status} ${response.statusText}`);
+ }
+ } catch (err) {
+ throw new Error(`Fetching fallback from ${url} failed: ${error.message(err)}`);
+ }
+ }
+
+ const buffer = await fs.readFile(cacheName);
+ await io.writeAsset({
+ pathname: assetPath,
+ buffer: buffer,
+ });
+ });
+ });
+ await Promise.all(fetchPromises);
+}
+
export async function fetchFont(ref: progress.Ref, name: string, sources: string[]) {
using _ = ref.start("fetch");
const errs = [];
@@ -82,6 +127,7 @@ export async function fetchFont(ref: progress.Ref, name: string, sources: string
cacheName,
new Uint8Array(await response.arrayBuffer()),
);
+ return cacheName;
} else {
errs.push(
new Error(
@@ -129,6 +175,7 @@ export async function fetchFont(ref: progress.Ref, name: string, sources: string
}
}
+ ASSERT(errs.length > 0);
throw new AggregateError(errs, `Failed to fetch the ${name} font`);
}
diff --git a/framework/generate.ts b/framework/generate.ts
index 844a0544bd8522a38735ff8745af14c18c08570b..d473e55b2df43164ec5341cef5f27c141c93a1e4 100644
--- a/framework/generate.ts
+++ b/framework/generate.ts
@@ -38,7 +38,7 @@ export async function generate(p: progress.Ref) {
);
}
- const builtFonts = fonts.buildFonts(p, siteConfig.fonts);
+ const builtFonts = fonts.buildFonts(p, siteConfig.fonts, siteConfig.meta.base);
await loadMarkoCache(p);
diff --git a/framework/watch.ts b/framework/watch.ts
index c639d69a5655222e3b6575d3e23ede4c810b6a57..c2dcdb20ccf325bc9f3735949300fef3e5c548d5 100644
--- a/framework/watch.ts
+++ b/framework/watch.ts
@@ -10,7 +10,7 @@ process.on("beforeExit", () => {
let watch: Watch;
export async function main() {
- child_process.execSync("./node_modules/.bin/dprint fmt .", { stdio: "inherit" });
+ child_process.execSync("./node_modules/.bin/dprint fmt --allow-no-files .", { stdio: "inherit" });
// Catch up state by running a main build.
if (!process.argv.includes("-f")) await incr.restore();
watch = new Watch(rebuild);
@@ -47,7 +47,9 @@ async function rebuild(files: string[]) {
try {
const formattingFiles = files.filter(x => !x.endsWith(".mdo"));
if (formattingFiles.length > 0) {
- child_process.execSync("./node_modules/.bin/dprint fmt " + formattingFiles.join(" "), { stdio: "inherit" });
+ child_process.execSync("./node_modules/.bin/dprint fmt --allow-no-files " + formattingFiles.join(" "), {
+ stdio: "inherit",
+ });
}
} catch (err) {
isRunning = false;
diff --git a/package-lock.json b/package-lock.json
index cb18fc6a5221f3ec0d7909d2f38e169097c187f9..6f0ca7c483219628ac9e1249a12400bf826a0b8f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -16,7 +16,7 @@
"harfbuzzjs": "0.10.1",
"hls.js": "1.6.5",
"hono": "4.12.8",
- "marko": "5.38.33",
+ "marko": "5.38.38",
"msgpackr": "1.11.5",
"playwright": "1.58.2",
"prettier": "^3.8.1",
@@ -694,9 +694,9 @@
}
},
"node_modules/@marko/runtime-tags": {
- "version": "6.0.159",
- "resolved": "https://registry.npmjs.org/@marko/runtime-tags/-/runtime-tags-6.0.159.tgz",
- "integrity": "sha512-gtw2oiqLKb1mbC+gsupbXL/BVBshNH2maDbiJ8s4L6BSmFlxkSmqJgkl6l6aCvoXqMh7PRqRZArwpT5RN9/Tpw==",
+ "version": "6.0.169",
+ "resolved": "https://registry.npmjs.org/@marko/runtime-tags/-/runtime-tags-6.0.169.tgz",
+ "integrity": "sha512-PApCgxeIOGR71TPx+BVwlNV9L2ej61hkDcB1ZBkCLKaUwJMdA9/LWEPMXNEJWB0Vn172iP/kwGIsi9dEPTPo1A==",
"license": "MIT",
"dependencies": {
"@marko/compiler": "^5.39.62",
@@ -1974,13 +1974,13 @@
}
},
"node_modules/marko": {
- "version": "5.38.33",
- "resolved": "https://registry.npmjs.org/marko/-/marko-5.38.33.tgz",
- "integrity": "sha512-e056TGqKjTE9CyO76eSlYLKk7P9z9uu0VGXt1Z3OrceCz728SCP/UhTas55ru9sNqihZEJ+vwv4ApwVwUsbtNg==",
+ "version": "5.38.38",
+ "resolved": "https://registry.npmjs.org/marko/-/marko-5.38.38.tgz",
+ "integrity": "sha512-dH5a6x/vcxb+fq/ZdWOTIuyz/Nf0kcdfWu9GwrGzl3AeM/FM2mAyp+szRssDmKYLw0VjxHiJTp3ddACSssVPPA==",
"license": "MIT",
"dependencies": {
"@marko/compiler": "^5.39.62",
- "@marko/runtime-tags": "^6.0.159",
+ "@marko/runtime-tags": "^6.0.169",
"app-module-path": "^2.2.0",
"argly": "^1.2.0",
"browser-refresh-client": "1.1.4",
diff --git a/package.json b/package.json
index 3e4dddc38106201f8016f350cf9c4413946505d7..c61f5b184b7ffdd5575a2e8884e19315358189bd 100644
--- a/package.json
+++ b/package.json
@@ -12,7 +12,7 @@
"harfbuzzjs": "0.10.1",
"hls.js": "1.6.5",
"hono": "4.12.8",
- "marko": "5.38.33",
+ "marko": "5.38.38",
"msgpackr": "1.11.5",
"playwright": "1.58.2",
"prettier": "^3.8.1",
diff --git a/src/file-viewer/backend.ts b/src/file-viewer/backend.ts
index f1844d651f884892ce690847fa1048a983a8bc52..3d1620101321ed90b4eaea57b6d02a2ab8c5d455 100644
--- a/src/file-viewer/backend.ts
+++ b/src/file-viewer/backend.ts
@@ -163,13 +163,13 @@ app.get("/file/*", async (c, next) => {
if (rangeHeader) {
const ranges = http.parseRangeHeader(rangeHeader, file.size);
if (ranges?.[0] && ranges.length === 1) {
- start = ranges[0][0];
- end = ranges[0][1];
+ start = ranges[0].start;
+ end = ranges[0].end;
status = 206;
headers.set(
"Content-Range",
- `bytes ${ranges[0][0]}-${ranges[0][1]}/${file.size}`,
+ `bytes ${ranges[0].start}-${ranges[0].end}/${file.size}`,
);
headers.delete("Content-Length");
} else {
diff --git a/src/pages/dream.mdo b/src/pages/dream.mdo
new file mode 100644
index 0000000000000000000000000000000000000000..6b7981d9a728e4f924f355cc3e40738f137e9af5
--- /dev/null
+++ b/src/pages/dream.mdo
@@ -0,0 +1,42 @@
+---
+meta:
+ title: paper clover's media license
+---
+
+
+
+[go back to the home page](/)
+
+# my life's dream
+
+if i could make art (music and videos) full time, forever, i would take that
+life in a heartbeat, never looking back. this has happened once in may 2025 for
+a month (an interlude between jobs). i called this **ART MONTH**, and it was the
+best month of my life. i want to do it again, for longer: **ART DECADE**. or if it was possible, **ART
+FOREVER**. the desire has been in me since age 16 or so. i don't want to work in
+the music industry, and i don't want to be contingent on my music being
+profitable. i want to make my art, the way i envision it.
+
+currently, i have a stupid tech job, which i am exceptionally good at. too good
+at it maybe. my knowledge and experience was built from doing crazy things in
+school and is the reason my colleagues rely on me for accurate technical advice.
+i'm the one to attempt and succeed with large, technically intricate projects.
+because of this, i make a cozy amount of money. this is convenient because it
+costs money to be alive. so, i'm saving and investing that money however
+possible to reach the level i could "retire" and get **ART DECADE** going.
+retire is the wrong word as i'll probably only work more.
+
+until then, the art here is done in my free time, elegantly balancing the time i
+spent on human connection, media consumption, and the art. i've learned so many
+times over that ruining this balance really fucks your head up.
+
+my one other dream is travel. not to places. but people. i love my friends with
+all my heart, and i want to visit all of them, especially the ones that wouldn't
+ever be able to travel to me. i do this a little now, but i only get so much
+time off work. if i could go to everyone.
+
+i will put in everything from my soul to make these two goals a reality.
+eventually, however long it takes.
+
+
+
diff --git a/src/pages/index.marko b/src/pages/index.marko
index 448626bfdf031548f45d473503bf822256cbcc62..a3505cebba22e26e742896c256925ac3bfff7143 100644
--- a/src/pages/index.marko
+++ b/src/pages/index.marko
@@ -20,30 +20,33 @@ export const meta = {
i am a girl that is adorable and
alive.
- this site contains my art.
- posts
+ art
+ webdev blog
+
things
links
diff --git a/src/pages/subscribe.marko b/src/pages/subscribe.marko
index 56c99777ed12e756144f53d82461c50a6295b9f3..943927bd0af760e23b2831bbca3200443d07e888 100644
--- a/src/pages/subscribe.marko
+++ b/src/pages/subscribe.marko
@@ -19,9 +19,7 @@ export const meta = {
i read every message, so you can say whatever else you want and i will see
- it. there won't be a confirmation email for subscribing. for those who are
- close friends with me, add your name and i'll add you to the 'friends' list,
- where i send life updates in addition to new content.
+ it. there won't be a confirmation email for subscribing.
to unsubscribe, send an email asking to unsubscribe.
--
2.54.0