Site · Logo: the letter E in iso blocks, in the header, the favicon, the touch icon and the OG image
One geometry in src/iso/mark.ts, drawn by the engine the miniatures use. The favicon follows the system's mode; scripts/favicon.mjs takes its colors from styles.css. Below 768px the header shows the mark alone, its word kept as the link's name.
This commit is contained in:
1 parent
faf0987cf8
commit
f80721abed
18 files changed
+158
-6
No files matched your search
@@ -0,0 +1,41 @@
|
||||
// Writes public/favicon.svg and public/apple-touch-icon.png from the header's mark.
|
||||
import { chromium } from "@playwright/test";
|
||||
import { readFileSync, writeFileSync } from "node:fs";
|
||||
import { mark, points } from "../src/iso/mark.ts";
|
||||
|
||||
const css = readFileSync("src/styles.css", "utf8");
|
||||
|
||||
/** The iso colors a `:root` block of styles.css sets, as the header's mark wears them. */
|
||||
function colors(selector) {
|
||||
const start = `\n${css}`.indexOf(`\n${selector} {`);
|
||||
const block = start < 0 ? null : css.slice(start, css.indexOf("}", start));
|
||||
if (!block) throw new Error(`favicon: styles.css has no ${selector} block`);
|
||||
const v = (name) => {
|
||||
const value = block.match(new RegExp(`--${name}: (#[0-9a-f]{6});`))?.[1];
|
||||
if (!value) throw new Error(`favicon: ${selector} sets no --${name}`);
|
||||
return value;
|
||||
};
|
||||
return { top: v("bg"), front: v("iso-side"), right: v("iso-shade"), line: v("iso-line"), accent: v("accent") };
|
||||
}
|
||||
const [LIGHT, DARK] = [colors(":root"), colors(":root.dark")];
|
||||
|
||||
const rules = (c) => `.top{fill:${c.top}}.front{fill:${c.front}}.right{fill:${c.right}}polygon{stroke:${c.line}}.accent{stroke:${c.accent}}`;
|
||||
|
||||
/** The mark centered in a square, `inset` of the side left round it. */
|
||||
function svg(inset, stroke, style, back = "") {
|
||||
const { width, height, polygons } = mark(0);
|
||||
const side = Math.max(width, height) / (1 - inset * 2);
|
||||
const [ox, oy] = [(side - width) / 2, (side - height) / 2];
|
||||
const body = polygons.map((p) => `<polygon class="${p.accent ? `${p.face} accent` : p.face}" points="${points(p.points.map(([x, y]) => [x + ox, y + oy]))}"/>`).join("");
|
||||
const fill = back && `<rect width="${side}" height="${side}" fill="${back}"/>`;
|
||||
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${+side.toFixed(3)} ${+side.toFixed(3)}" stroke-width="${stroke}" stroke-linejoin="round"><style>${style}</style>${fill}${body}</svg>\n`;
|
||||
}
|
||||
|
||||
writeFileSync("public/favicon.svg", svg(0.04, 0.28, `${rules(LIGHT)}@media (prefers-color-scheme:dark){${rules(DARK)}}`));
|
||||
|
||||
const browser = await chromium.launch();
|
||||
const page = await browser.newPage({ viewport: { width: 180, height: 180 } });
|
||||
await page.setContent(`<style>body{margin:0}svg{display:block;width:180px;height:180px}</style>${svg(0.18, 0.16, rules(LIGHT), LIGHT.top)}`);
|
||||
await page.screenshot({ path: "public/apple-touch-icon.png" });
|
||||
await browser.close();
|
||||
console.log("favicon: wrote public/favicon.svg and public/apple-touch-icon.png");
|
||||
@@ -4,7 +4,7 @@ import { chromium } from "@playwright/test";
|
||||
const browser = await chromium.launch();
|
||||
const page = await browser.newPage({ viewport: { width: 1200, height: 630 }, deviceScaleFactor: 2, colorScheme: "light", reducedMotion: "reduce" });
|
||||
await page.goto(process.env.SITE ?? "http://localhost:4173/");
|
||||
await page.addStyleTag({ content: ".bar, .skip, .hero .button { display: none } .hero { min-height: 630px; height: 630px; padding: 56px } .hero-iso { top: 0; height: 100% }" });
|
||||
await page.addStyleTag({ content: ".bar nav, .bar .end, .skip, .hero .button { display: none } .bar { background: none; backdrop-filter: none; padding: 0 56px } .hero { min-height: 630px; height: 630px; padding: 56px } .hero-iso { top: 0; height: 100% }" });
|
||||
await page.waitForSelector(".hero-iso");
|
||||
await page.waitForTimeout(800);
|
||||
await page.screenshot({ path: "public/og.png", clip: { x: 0, y: 0, width: 1200, height: 630 } });
|
||||
|
||||
Reference in new issue
Block a user