63 lines
2.2 KiB
TypeScript
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.ico" />
|
|
<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>`;
|
|
}
|