Inject CMS meta tags as full HTML from business-info.

metaTags is now { html }; parse into head <meta> elements instead of name/content metadata.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-10-03 18:39:21 +03:30
co-authored by Cursor
parent f60c98184b
commit 7ea3fe76c9
2 changed files with 32 additions and 8 deletions
+15 -6
View File
@@ -6,7 +6,12 @@ import { TopBar } from "@/components/home/TopBar";
import { Header } from "@/components/home/Header";
import { Footer } from "@/components/home/Footer";
import { Providers } from "@/context/Providers";
import { getBusinessInfo, getCategories, getCategoryTree } from "@/lib/meshkee";
import {
getBusinessInfo,
getCategories,
getCategoryTree,
parseMetaTagHtml,
} from "@/lib/meshkee";
// Body text — headings use the bold weight instead, see globals.css.
const iranyekan = localFont({
@@ -29,16 +34,11 @@ const syne = Syne({
export async function generateMetadata(): Promise<Metadata> {
const businessInfo = await getBusinessInfo();
const other: Record<string, string> = {};
for (const tag of businessInfo?.metaTags ?? []) {
if (tag.name && tag.content) other[tag.name] = tag.content;
}
return {
title: "صنیع هوم | فروشگاه لوازم خانگی",
description: "فروشگاه آنلاین لوازم خانگی — یخچال، لباسشویی، تلویزیون و بیشتر",
icons: businessInfo?.faviconUrl ? [{ url: businessInfo.faviconUrl }] : undefined,
...(Object.keys(other).length > 0 ? { other } : {}),
};
}
@@ -49,12 +49,21 @@ export default async function RootLayout({ children }: LayoutProps<"/">) {
getBusinessInfo(),
]);
const cmsMetaTags = (businessInfo?.metaTags ?? [])
.map((tag, index) => {
const attrs = parseMetaTagHtml(tag.html ?? "");
if (!attrs) return null;
return <meta key={`cms-meta-${index}`} {...attrs} />;
})
.filter(Boolean);
return (
<html
lang="fa"
dir="rtl"
className={`${iranyekan.variable} ${iranyekanBold.variable} ${syne.variable} h-full antialiased`}
>
{cmsMetaTags.length > 0 ? <head>{cmsMetaTags}</head> : null}
<body className="min-h-full flex flex-col">
<Providers>
<TopBar />
+17 -2
View File
@@ -44,11 +44,26 @@ async function apiPost<T>(
}
}
/** Full sanitized `<meta …>` HTML from business-info. */
export type BusinessMetaTag = {
name: string;
content: string;
html: string;
};
/** Parse a single `<meta …>` tag into React/Next attribute props. */
export function parseMetaTagHtml(html: string): Record<string, string> | null {
const match = html.trim().match(/^<meta\b([^>]*)\/?\s*>$/i);
if (!match) return null;
const attrs: Record<string, string> = {};
const attrRe = /([:\w.-]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?/g;
let m: RegExpExecArray | null;
while ((m = attrRe.exec(match[1]))) {
const key = m[1].toLowerCase();
if (key === '/') continue;
attrs[key] = m[2] ?? m[3] ?? m[4] ?? '';
}
return Object.keys(attrs).length > 0 ? attrs : null;
}
export type BusinessTrustBadge = {
kind: "enamad" | "samandehi";
embedHtml: string;