From 73849b7f04b1f4c9c957fad1a6b50f87e9f71a7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20=E2=80=9CAd=C3=A6dra=E2=80=9D=20Hamel?= Date: Mon, 24 Jun 2024 19:31:11 +0200 Subject: [PATCH] Global asset management --- lib/assets.ts | 27 +++++++++++++++++++++++++++ lib/hash.ts | 11 ----------- lib/postcss/hashes.ts | 10 +++++----- lib/tasks/articles.ts | 20 +++----------------- src/article.tsx | 4 ++-- src/index.tsx | 19 +++++++------------ src/layout.tsx | 4 ++-- 7 files changed, 46 insertions(+), 49 deletions(-) create mode 100644 lib/assets.ts diff --git a/lib/assets.ts b/lib/assets.ts new file mode 100644 index 0000000..a9401ad --- /dev/null +++ b/lib/assets.ts @@ -0,0 +1,27 @@ +import { globSync } from "glob"; +import { readFileSync } from "node:fs"; +import { env } from "node:process"; +import { join } from "node:path"; + +export const assetMap: Map = new Map(); + +export function reloadAssets() { + assetMap.clear(); + + globSync("dist/_assets/*.manifest") + .map( + (manifest) => + JSON.parse(readFileSync(manifest).toString()) as { [orig: string]: string }, + ) + .forEach((mapping) => + Object.entries(mapping).forEach(([orig, hashed]) => assetMap.set(orig, hashed)), + ); +} + +export function asset(path: string): string { + const realPath = assetMap.has(path) ? assetMap.get(path) : path; + + return env.ASSETS_HOSTS + ? new URL(realPath, env.ASSETS_HOSTS).toString() + : join("/_assets/", realPath); +} diff --git a/lib/hash.ts b/lib/hash.ts index a698f77..2dae20a 100644 --- a/lib/hash.ts +++ b/lib/hash.ts @@ -1,19 +1,8 @@ import { Transform } from "node:stream"; import { createHash } from "node:crypto"; import File from "vinyl"; -import { globSync } from "glob"; -import { readFileSync } from "node:fs"; import { PRODUCTION } from "./environment.js"; -export function readAssetManifest(): { [entry: string]: string } { - return Object.assign( - {}, - ...globSync("dist/_assets/*.manifest").map((path) => - JSON.parse(readFileSync(path).toString()), - ), - ); -} - function fileHash(buffer: Buffer) { const hash = createHash("sha256"); hash.update(buffer.toString()); diff --git a/lib/postcss/hashes.ts b/lib/postcss/hashes.ts index 464df10..df20e26 100644 --- a/lib/postcss/hashes.ts +++ b/lib/postcss/hashes.ts @@ -1,16 +1,16 @@ import Postcss from "postcss"; -import { readAssetManifest } from "../hash.js"; +import { reloadAssets, assetMap } from "../assets.js"; -export default (opts: any = {}): Postcss.Plugin => { +export default (): Postcss.Plugin => { return { postcssPlugin: "postcss-hashes", Once() { - opts._mappings = readAssetManifest(); + reloadAssets(); }, Declaration(decl: Postcss.Declaration) { decl.value = decl.value.replace(/url\("([^"]+)"\)/, (v, url) => { - if (opts._mappings.hasOwnProperty(url)) { - return v.replace(url, opts._mappings[url]); + if (assetMap.has(url)) { + return v.replace(url, assetMap.get(url)); } return v; diff --git a/lib/tasks/articles.ts b/lib/tasks/articles.ts index 6ec0bf2..5338f11 100644 --- a/lib/tasks/articles.ts +++ b/lib/tasks/articles.ts @@ -1,5 +1,4 @@ import { readFileSync } from "node:fs"; -import { env } from "node:process"; import { join, basename, dirname } from "node:path"; import { Transform } from "node:stream"; import asciidoctor, { Document } from "asciidoctor"; @@ -14,13 +13,13 @@ import { PRODUCTION, DEFAULT_DATE } from "../environment.js"; import rehypeExternalLinks from "rehype-external-links"; import visit from "unist-util-visit"; import { src, dest } from "gulp"; -import { readAssetManifest } from "../hash.js"; import renderLayout from "../../src/layout.js"; import renderArticleLayout from "../../src/article.js"; import renderIndex from "../../src/index.js"; import { renderToStaticMarkup } from "preact-render-to-string"; import { SITE_TITLE, SITE_DESCRIPTION } from "../../src/constants.js"; import { JSX } from "preact/jsx-runtime"; +import { reloadAssets } from "../assets.js"; const Asciidoctor = asciidoctor(); const EXTENSION_REGISTRY = Asciidoctor.Extensions.create(); @@ -60,17 +59,7 @@ function renderDocument(root: JSX.Element): Buffer { function renderArticle() { const allArticles: [string, DateTime, Document][] = []; - const assetManifest = readAssetManifest(); - - const asset = (path: string) => { - if (assetManifest.hasOwnProperty(path)) { - path = assetManifest[path]; - } - - return env.ASSETS_HOSTS - ? new URL(path, env.ASSETS_HOSTS).toString() - : join("/_assets/", path); - }; + reloadAssets(); return new Transform({ readableObjectMode: true, @@ -98,7 +87,6 @@ function renderArticle() { .use(rehypeStringify) .process(article.convert()); const content = renderLayout({ - asset, title: article.getDoctitle({}) as string, meta: { description: article.getAttribute("description"), @@ -112,7 +100,6 @@ function renderArticle() { }, Content: () => renderArticleLayout({ - asset, article, date, body: vfile.toString(), @@ -133,14 +120,13 @@ function renderArticle() { try { allArticles.sort(([, a], [, b]) => b.diff(a).toMillis()); const contents = renderLayout({ - asset, meta: { description: SITE_DESCRIPTION, "og:title": SITE_TITLE, "og:type": "website", "og:url": `https://adaedra.eu`, }, - Content: () => renderIndex({ articles: allArticles, asset }), + Content: () => renderIndex({ articles: allArticles }), }); this.push( diff --git a/src/article.tsx b/src/article.tsx index 2d2ca77..eab5006 100644 --- a/src/article.tsx +++ b/src/article.tsx @@ -1,14 +1,14 @@ import { Document } from "asciidoctor"; import { DateTime } from "luxon"; +import { asset } from "../lib/assets.js"; type Props = { article: Document; date: DateTime; body: string; - asset(path: string): string; }; -export default ({ asset, article, date, body }: Props) => ( +export default ({ article, date, body }: Props) => ( <>