strava-frontend/server/template.ts

63 lines
2.2 KiB
TypeScript

import fs from "fs";
import path from "path";
export interface SeoMeta {
title: string;
description: string;
canonicalUrl: string;
ogImage?: string;
jsonLd?: Record<string, unknown>;
}
export interface TemplateOptions {
meta: SeoMeta;
content: string; // HTML content to inject inside <div id="app">
assetTags: string; // <script>/<link> tags from built dist/index.html
}
/**
* Read built dist/index.html and extract <script> and <link rel="stylesheet"> tags.
* This ensures we always reference the correct hashed asset filenames.
*/
export function getAssetTags(): string {
const distPath = process.env.DIST_PATH || path.resolve(__dirname, "../dist");
const distIndex = path.join(distPath, "index.html");
const html = fs.readFileSync(distIndex, "utf-8");
const scriptMatch = html.match(/<script[^>]*src="[^"]*"[^>]*><\/script>/g);
const linkMatch = html.match(/<link[^>]*rel="stylesheet"[^>]*>/g);
return [...(linkMatch || []), ...(scriptMatch || [])].join("\n ");
}
export function renderTemplate(options: TemplateOptions): string {
const { meta, content, assetTags } = options;
const jsonLdScript = meta.jsonLd
? `\n <script type="application/ld+json">${JSON.stringify(meta.jsonLd)}</script>`
: "";
return `<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="yandex-verification" content="81ff150ccc5ab8c6" />
<title>${meta.title}</title>
<meta name="description" content="${meta.description}" />
<link rel="canonical" href="${meta.canonicalUrl}" />
<meta property="og:title" content="${meta.title}" />
<meta property="og:description" content="${meta.description}" />
<meta property="og:type" content="website" />
<meta property="og:url" content="${meta.canonicalUrl}" />
${meta.ogImage ? `<meta property="og:image" content="${meta.ogImage}" />` : ""}
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet" />
${assetTags}
${jsonLdScript}
</head>
<body>
<div id="app">
${content}
</div>
</body>
</html>`;
}