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 +--- +
this site contains my art.
-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.