From 4548289ecf2c1d428f34a263da7a876bc5fe5fa7 Mon Sep 17 00:00:00 2001 From: Prad Nukala Date: Wed, 30 Sep 2026 16:31:18 -0400 Subject: [PATCH] feat(config): tag changelog releases by Topic or Review category --- apps/docs/blume.config.ts | 83 ++++++++++++++++++++++++++++----------- 1 file changed, 60 insertions(+), 23 deletions(-) diff --git a/apps/docs/blume.config.ts b/apps/docs/blume.config.ts index 0d050fa..3ec2774 100644 --- a/apps/docs/blume.config.ts +++ b/apps/docs/blume.config.ts @@ -1,21 +1,25 @@ import { defineConfig } from "blume"; import type { StandardSchema } from "blume/core/standard-schema.ts"; +import { hashText } from "blume/core/sources/cache.ts"; +import type { ContentSource } from "blume/core/sources/types.ts"; import { custom, filesystem } from "blume/sources"; import { githubReleasesSource } from "blume/sources/github-releases.ts"; import redirects from "./redirects"; /** - * GitHub releases → /changelog, dated by the topic's real finish instant. + * GitHub releases → /changelog, dated by the real finish instant of the topic + * or `Review — ` issue each release records. * * Blume dates a release entry by `published_at`, which the GitHub API cannot - * backdate — so the topic releases backfilled on one day (apps/cli/ + * backdate — so the releases backfilled on one day (apps/cli/ * release-topics.ts) would all read that day. Their tags are timever - * (`YYYYMMDD.HHMMSS.NNNNNNNNN`, UTC) of the moment the topic finished, so this - * fetch rewrites each timever release's `published_at` to that instant before - * Blume maps it; anything else passes through untouched. The config-level - * `githubReleases()` accepts no `fetchImpl`, hence the `custom()` wrap of the - * underlying source (the `blume/sources/*.ts` path the Blume docs use for - * custom sources), with the context the built-in adapter would receive. + * (`YYYYMMDD.HHMMSS.NNNNNNNNN`, UTC) of the moment the topic or review + * finished, so this fetch rewrites each timever release's `published_at` to + * that instant before Blume maps it; anything else passes through untouched. + * The config-level `githubReleases()` accepts no `fetchImpl`, hence the + * `custom()` wrap of the underlying source (the `blume/sources/*.ts` path the + * Blume docs use for custom sources), with the context the built-in adapter + * would receive. */ const TIMEVER = /^(\d{4})(\d{2})(\d{2})\.(\d{2})(\d{2})(\d{2})\.\d{9}$/; @@ -38,6 +42,37 @@ const releasesDatedByTag: typeof fetch = async (input, init) => { return Response.json(releases, { status: res.status }); }; +/** + * The changelog index tags every row with `changelog.category`, which the + * GitHub source sets to "Release" for all of them. release-topics.ts names + * each release after its issue, so the title prefix says which kind finished + * — a topic's core set, or a Review day block — and the row is tagged + * `Topic` / `Review` instead. The category lives both in `data` and in the + * staged `raw` frontmatter Astro re-parses, so both are rewritten (and the + * hash with them). Wrapped around the source Blume rebuilds via + * `withContext`, so the rebuilt one is tagged too. + */ +const RELEASE_KIND = /^(Topic|Review) \d+ — /; + +const releasesByKind = (source: ContentSource): ContentSource => ({ + ...source, + load: async () => { + const result = await source.load(); + for (const entry of result.entries) { + const kind = typeof entry.data.title === "string" ? entry.data.title.match(RELEASE_KIND)?.[1] : undefined; + const changelog = entry.data.changelog; + if (!kind || !changelog || typeof changelog !== "object" || !("category" in changelog)) continue; + changelog.category = kind; + if (entry.raw) { + entry.raw = entry.raw.replace(/^( {2}category: ).*$/m, `$1${kind}`); + entry.hash = hashText(entry.raw); + } + } + return result; + }, + withContext: source.withContext && ((ctx) => releasesByKind(source.withContext!(ctx))), +}); + // Blume's defaults (`inter`, `ibm-plex-mono`) are fetched from fonts.gstatic.com // on every build, which has timed out on the Pages runner and, fully offline, // silently ships no fonts at all. The same two families from Fontsource, as @@ -151,21 +186,23 @@ export default defineConfig({ sources: [ filesystem({ root: "content" }), custom( - githubReleasesSource( - { - name: "changelog", - prefix: "changelog", - owner: "prdlk", - repo: "leetcode", - fetchImpl: releasesDatedByTag, - }, - // What resolve.ts hands the built-in adapter: `.blume/cache//`, - // and a refresh on every load (the source reads nothing else). - { - projectRoot: import.meta.dirname, - cacheDir: `${import.meta.dirname}/.blume/cache/changelog`, - mode: "build", - }, + releasesByKind( + githubReleasesSource( + { + name: "changelog", + prefix: "changelog", + owner: "prdlk", + repo: "leetcode", + fetchImpl: releasesDatedByTag, + }, + // What resolve.ts hands the built-in adapter: `.blume/cache//`, + // and a refresh on every load (the source reads nothing else). + { + projectRoot: import.meta.dirname, + cacheDir: `${import.meta.dirname}/.blume/cache/changelog`, + mode: "build", + }, + ), ), ), ],