| 1 |
|
- |
import { $ } from "bun"; |
|
1 |
+ |
import { $, Glob } from "bun"; |
|
2 |
+ |
import { rm } from "node:fs/promises"; |
| 2 |
3 |
|
|
| 3 |
|
- |
// Clean up dist |
| 4 |
|
- |
await $`rm -rf site-dist`; |
| 5 |
|
- |
// Create new dist |
| 6 |
|
- |
await $`cp -r site site-dist`; |
| 7 |
|
- |
// Compile tailwindcss |
| 8 |
|
- |
await $`bunx @tailwindcss/cli -i ./site/input.css -o ./site-dist/output.css `; |
|
4 |
+ |
const OUT = "site-dist"; |
|
5 |
+ |
// Dev placeholder that bun-plugin-tailwind resolves; must be rewritten for prod. |
|
6 |
+ |
const PLACEHOLDER = `<link rel="stylesheet" href="tailwindcss" />`; |
| 9 |
7 |
|
|
| 10 |
|
- |
// Read index file |
| 11 |
|
- |
const htmlContent = await Bun.file("site-dist/index.html").text(); |
| 12 |
|
- |
// Update script tags and css link |
| 13 |
|
- |
const updatedHtml = htmlContent |
| 14 |
|
- |
.replace( |
| 15 |
|
- |
`<link rel="stylesheet" href="tailwindcss" />`, |
| 16 |
|
- |
`<link rel="stylesheet" href="output.css" />`, |
| 17 |
|
- |
); |
| 18 |
|
- |
// Write file |
| 19 |
|
- |
await Bun.write("site-dist/index.html", updatedHtml); |
|
8 |
+ |
// Fresh copy of the static site |
|
9 |
+ |
await $`rm -rf ${OUT}`; |
|
10 |
+ |
await $`cp -r site ${OUT}`; |
| 20 |
11 |
|
|
| 21 |
|
- |
// Read feeds file |
| 22 |
|
- |
const feedsContent = await Bun.file("site-dist/feeds.html").text(); |
| 23 |
|
- |
// Update script tags and css link |
| 24 |
|
- |
const updatedFeedsHtml = feedsContent |
| 25 |
|
- |
.replace( |
| 26 |
|
- |
`<link rel="stylesheet" href="tailwindcss" />`, |
| 27 |
|
- |
`<link rel="stylesheet" href="/output.css" />`, |
|
12 |
+ |
// Compile + minify Tailwind |
|
13 |
+ |
await $`bunx @tailwindcss/cli -i ./site/input.css -o ./${OUT}/assets/styles.css --minify`; |
|
14 |
+ |
|
|
15 |
+ |
// Content-hash the stylesheet so it can be cached immutably |
|
16 |
+ |
const css = Bun.file(`${OUT}/assets/styles.css`); |
|
17 |
+ |
const hash = Bun.hash(await css.arrayBuffer()).toString(16).slice(0, 8); |
|
18 |
+ |
const cssPath = `/assets/styles.${hash}.css`; |
|
19 |
+ |
await Bun.write(`${OUT}${cssPath}`, css); |
|
20 |
+ |
await rm(`${OUT}/assets/styles.css`); |
|
21 |
+ |
|
|
22 |
+ |
// The Tailwind source isn't needed in the deployed output |
|
23 |
+ |
await rm(`${OUT}/input.css`, { force: true }); |
|
24 |
+ |
|
|
25 |
+ |
// Point every page at the built stylesheet |
|
26 |
+ |
for (const file of new Glob("*.html").scanSync(OUT)) { |
|
27 |
+ |
const path = `${OUT}/${file}`; |
|
28 |
+ |
const html = await Bun.file(path).text(); |
|
29 |
+ |
if (!html.includes(PLACEHOLDER)) { |
|
30 |
+ |
throw new Error( |
|
31 |
+ |
`${file}: expected stylesheet placeholder ${PLACEHOLDER} — CSS would 404`, |
|
32 |
+ |
); |
|
33 |
+ |
} |
|
34 |
+ |
await Bun.write( |
|
35 |
+ |
path, |
|
36 |
+ |
html.replaceAll( |
|
37 |
+ |
PLACEHOLDER, |
|
38 |
+ |
`<link rel="stylesheet" href="${cssPath}" />`, |
|
39 |
+ |
), |
| 28 |
40 |
|
); |
| 29 |
|
- |
// Write file |
| 30 |
|
- |
await Bun.write("site-dist/feeds.html", updatedFeedsHtml); |
|
41 |
+ |
console.log(`✓ ${file} → ${cssPath}`); |
|
42 |
+ |
} |