Rebuild Docker setup with simplified nginx-only Dockerfile (build runs on host). Add category detail pages, IRANSans font files, product images, and update all landing sections. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
100 lines
2.7 KiB
TypeScript
100 lines
2.7 KiB
TypeScript
import { absUrl as abs, siteConfig as s } from "../config/site";
|
|
|
|
type Json = Record<string, unknown>;
|
|
|
|
const clean = <T extends object>(o: T): Json =>
|
|
JSON.parse(
|
|
JSON.stringify(o, (_, v) =>
|
|
v === "" || (Array.isArray(v) && !v.length) ? undefined : v,
|
|
),
|
|
);
|
|
|
|
export const organizationSchema = () =>
|
|
clean({
|
|
"@context": "https://schema.org",
|
|
"@type": "LocalBusiness",
|
|
"@id": `${s.url}/#organization`,
|
|
name: s.name,
|
|
alternateName: s.nameEn,
|
|
url: abs("/"),
|
|
logo: abs(s.logo),
|
|
image: abs(s.logo),
|
|
description: s.description,
|
|
email: s.contact.email,
|
|
telephone: s.contact.phone,
|
|
foundingDate: s.foundingDate,
|
|
areaServed: s.areaServed,
|
|
address: {
|
|
"@type": "PostalAddress",
|
|
streetAddress: s.contact.address.streetAddress,
|
|
addressLocality: s.contact.address.addressLocality,
|
|
addressCountry: s.contact.address.addressCountry,
|
|
},
|
|
openingHoursSpecification: {
|
|
"@type": "OpeningHoursSpecification",
|
|
dayOfWeek: s.openingHours.days,
|
|
opens: s.openingHours.opens,
|
|
closes: s.openingHours.closes,
|
|
},
|
|
sameAs: s.socials,
|
|
});
|
|
|
|
export const websiteSchema = () => ({
|
|
"@context": "https://schema.org",
|
|
"@type": "WebSite",
|
|
"@id": `${s.url}/#website`,
|
|
url: abs("/"),
|
|
name: s.name,
|
|
inLanguage: s.lang,
|
|
publisher: { "@id": `${s.url}/#organization` },
|
|
});
|
|
|
|
export const serviceSchema = (opts: {
|
|
name: string;
|
|
description: string;
|
|
areaServed?: string;
|
|
}) =>
|
|
clean({
|
|
"@context": "https://schema.org",
|
|
"@type": "Service",
|
|
name: opts.name,
|
|
description: opts.description,
|
|
areaServed: opts.areaServed ?? s.areaServed,
|
|
provider: { "@id": `${s.url}/#organization` },
|
|
});
|
|
|
|
export const categoryPageSchema = (category: {
|
|
name: string;
|
|
en: string;
|
|
fullDesc: string;
|
|
slug: string;
|
|
products: { name: string; desc: string }[];
|
|
}) =>
|
|
clean({
|
|
"@context": "https://schema.org",
|
|
"@type": "CollectionPage",
|
|
"@id": `${s.url}/categories/${category.slug}`,
|
|
name: category.name,
|
|
description: category.fullDesc,
|
|
url: abs(`/categories/${category.slug}`),
|
|
isPartOf: { "@id": `${s.url}/#website` },
|
|
provider: { "@id": `${s.url}/#organization` },
|
|
mainEntity: {
|
|
"@type": "ItemList",
|
|
numberOfItems: category.products.length,
|
|
itemListElement: category.products.map((p, i) => ({
|
|
"@type": "ListItem",
|
|
position: i + 1,
|
|
item: {
|
|
"@type": "Product",
|
|
name: p.name,
|
|
description: p.desc,
|
|
},
|
|
})),
|
|
},
|
|
});
|
|
|
|
/** Serialize JSON-LD safely for an inline <script> (escape "<"). */
|
|
export const toJsonLd = (data: Json) =>
|
|
JSON.stringify(data).replace(/</g, "\\u003c");
|