fix: load system fonts for OG image text rendering

usvg's default Options creates an empty fontdb, so no fonts are found
for text rendering regardless of what's installed. Load system fonts
into a fontdb::Database and set the default font family to Noto Sans.

Also picks up a formatting change to index.html from a linter.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-11 16:17:17 +03:00
parent d539892b70
commit 1f2fea3427
4 changed files with 67 additions and 23 deletions

View File

@@ -31,6 +31,7 @@ reqwest = { version = "0.12", default-features = false, features = ["rustls-tls"
figment = { version = "0.10", features = ["toml", "env"] } figment = { version = "0.10", features = ["toml", "env"] }
clap = { version = "4", features = ["derive", "env"] } clap = { version = "4", features = ["derive", "env"] }
resvg = "0.45" resvg = "0.45"
fontdb = "0.23"
# internal # internal
moments-entities = { path = "crates/moments-entities", version = "=0.1.0" } moments-entities = { path = "crates/moments-entities", version = "=0.1.0" }

View File

@@ -22,3 +22,4 @@ chrono.workspace = true
clap.workspace = true clap.workspace = true
reqwest.workspace = true reqwest.workspace = true
resvg.workspace = true resvg.workspace = true
fontdb.workspace = true

View File

@@ -360,7 +360,12 @@ fn render_contributions_png(
svg.push_str("</svg>"); svg.push_str("</svg>");
// Rasterize at 1200x630 // Rasterize at 1200x630
let tree = resvg::usvg::Tree::from_str(&svg, &resvg::usvg::Options::default()) let mut fontdb = fontdb::Database::new();
fontdb.load_system_fonts();
let mut opts = resvg::usvg::Options::default();
opts.fontdb = std::sync::Arc::new(fontdb);
opts.font_family = "Noto Sans".to_owned();
let tree = resvg::usvg::Tree::from_str(&svg, &opts)
.map_err(|e| format!("svg parse: {e}"))?; .map_err(|e| format!("svg parse: {e}"))?;
let mut pixmap = let mut pixmap =

View File

@@ -1,25 +1,62 @@
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>rob.tn</title> <title>rob.tn</title>
<meta property="og:title" content="rob thijssen — developer activity and contribution history" /> <meta
<meta property="og:description" content="a timeline of open source contributions across github, gitea, and mozilla hg — ranked projects, language trends, and commit activity since 2012." /> property="og:title"
<meta property="og:image" content="https://rob.tn/api/v1/og/contributions.png" /> content="rob thijssen: developer activity and contribution history"
<meta property="og:type" content="website" /> />
<meta name="twitter:card" content="summary_large_image" /> <meta
<meta name="twitter:image" content="https://rob.tn/api/v1/og/contributions.png" /> property="og:description"
<link rel="icon" type="image/x-icon" href="/favicon.ico" /> content="a timeline of open source contributions across github, gitea, and mozilla hg — ranked projects, language trends, and commit activity since 2012."
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16.png" /> />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32.png" /> <meta
<link rel="icon" type="image/png" sizes="48x48" href="/favicon-48.png" /> property="og:image"
<link rel="apple-touch-icon" href="/apple-touch-icon.png" /> content="https://rob.tn/api/v1/og/contributions.png"
<link rel="icon" type="image/png" sizes="192x192" href="/icon-192.png" /> />
<link rel="icon" type="image/png" sizes="512x512" href="/icon-512.png" /> <meta property="og:type" content="website" />
</head> <meta name="twitter:card" content="summary_large_image" />
<body> <meta
<div id="root"></div> name="twitter:image"
<script type="module" src="/src/main.tsx"></script> content="https://rob.tn/api/v1/og/contributions.png"
</body> />
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<link
rel="icon"
type="image/png"
sizes="16x16"
href="/favicon-16.png"
/>
<link
rel="icon"
type="image/png"
sizes="32x32"
href="/favicon-32.png"
/>
<link
rel="icon"
type="image/png"
sizes="48x48"
href="/favicon-48.png"
/>
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
<link
rel="icon"
type="image/png"
sizes="192x192"
href="/icon-192.png"
/>
<link
rel="icon"
type="image/png"
sizes="512x512"
href="/icon-512.png"
/>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html> </html>