diff --git a/client/public/og-image.jpg b/client/public/og-image.jpg index 3ada40b..f8d8798 100644 Binary files a/client/public/og-image.jpg and b/client/public/og-image.jpg differ diff --git a/server/static.ts b/server/static.ts index d40b38f..bed74fa 100644 --- a/server/static.ts +++ b/server/static.ts @@ -2,11 +2,41 @@ import express, { type Express } from "express"; import fs from "fs"; import path from "path"; import { storage } from "./storage"; +import sharp from "sharp"; function escapeHtml(str: string): string { return str.replace(/&/g, "&").replace(/"/g, """).replace(//g, ">"); } +// Dejanske dimenzije naslovnice. Prej sta bili sirina in visina v meta +// oznakah fiksno zapisani kot 1200x630, slike pa so v resnici 1200x900 — +// Facebook in Google sta dobila napacno vrednost. Ce dimenzij ne moremo +// prebrati, oznak raje ne zapisemo. +const ogDimCache = new Map(); + +async function ogImageDims(imgUrl: string, publicDir: string) { + if (ogDimCache.has(imgUrl)) return ogDimCache.get(imgUrl) ?? null; + let dims: { w: number; h: number } | null = null; + try { + const m = /\/(uploads|images)\/([^/?#]+)$/.exec(imgUrl); + if (m) { + const cand = [ + path.join(publicDir, m[1], m[2]), + path.join(publicDir, m[1], m[2].replace(/\.jpg$/, ".webp")), + ]; + for (const p of cand) { + if (!fs.existsSync(p)) continue; + const meta = await sharp(p).metadata(); + if (meta.width && meta.height) { dims = { w: meta.width, h: meta.height }; break; } + } + } + } catch (e) { + dims = null; + } + ogDimCache.set(imgUrl, dims); + return dims; +} + function ogImageUrl(coverImage: string, baseUrl: string): string { if (!coverImage) return ""; let imgPath = coverImage; @@ -173,6 +203,10 @@ export function serveStatic(app: Express) { const articleUrl = `${canonicalBase}/article/${article.slug}`; const imageUrl = ogImageUrl(article.coverImage || "", canonicalBase); const finalImage = imageUrl || `${canonicalBase}/og-image.jpg`; + const articleImgDims = await ogImageDims(finalImage, distPath); + if (!imageUrl) { + console.warn(`[og] clanek brez naslovnice, pada na logotip: ${article.slug}`); + } let template = await fs.promises.readFile(indexPath, "utf-8"); template = stripExistingMeta(template); @@ -249,8 +283,10 @@ export function serveStatic(app: Express) { ``, ``, ``, - ``, - ``, + ...(articleImgDims + ? [``, + ``] + : []), ``, ``, ``,