feat(breadcrumb): implement BreadcrumbList structure and validation for SEO compliance
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
// ساخت BreadcrumbList معتبر برای schema.org — منبع واحدِ همهٔ breadcrumbهای سایت.
|
||||
//
|
||||
// چرا این فایل هست: سرچکنسول روی nobat724.com خطای بحرانی
|
||||
// «Missing field "item" (in "itemListElement")» میداد. علتش این بود که
|
||||
// `item` فقط وقتی اضافه میشد که هم href داشته باشیم هم origin — و در
|
||||
// /clinics اصلاً origin پاس داده نمیشد، پس هیچکدام از عنصرها `item` نداشتند و
|
||||
// کل BreadcrumbList نامعتبر میشد.
|
||||
//
|
||||
// قاعدهای که اینجا تضمین میشود: یا **همهٔ** عنصرها `item` مطلق دارند، یا اصلاً
|
||||
// JSON-LD تولید نمیشود. اسکیمای ناقص از نبودِ اسکیما بدتر است (صفحه از rich
|
||||
// resultها حذف میشود و در سرچکنسول بهعنوان خطای بحرانی مینشیند).
|
||||
//
|
||||
// list: Array<string | { name, href }> — همیشه href بده، حتی برای آیتم آخر
|
||||
// (صفحهٔ جاری)؛ ظاهر تغییری نمیکند چون آیتم آخر هرگز لینک نمیشود.
|
||||
|
||||
/** ورودی خام را به [{name, href}] یکدست میکند و بینامها را میاندازد. */
|
||||
export function normalizeBreadcrumb(list = []) {
|
||||
return (Array.isArray(list) ? list : [])
|
||||
.map((item) => (typeof item === "string" ? { name: item } : item))
|
||||
.filter((item) => item && typeof item.name === "string" && item.name.trim() !== "");
|
||||
}
|
||||
|
||||
/** origin + href → URL مطلق. هر ورودی ناقص → null. */
|
||||
export function absoluteUrl(origin, href) {
|
||||
if (!origin || typeof href !== "string" || href === "") return null;
|
||||
if (/^https?:\/\//i.test(href)) return href;
|
||||
const base = String(origin).replace(/\/+$/, "");
|
||||
const path = href.startsWith("/") ? href : `/${href}`;
|
||||
return path === "/" ? base : `${base}${path}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* BreadcrumbList معتبر، یا `null` وقتی حتی یک عنصر URL مطلق ندارد.
|
||||
* @returns {object|null}
|
||||
*/
|
||||
export function buildBreadcrumbJsonLd(list, origin) {
|
||||
const items = normalizeBreadcrumb(list);
|
||||
if (items.length === 0) return null;
|
||||
|
||||
const elements = [];
|
||||
for (const [idx, item] of items.entries()) {
|
||||
const url = absoluteUrl(origin, item.href);
|
||||
if (!url) return null; // بدون item کاملِ همهٔ عنصرها، اسکیما را منتشر نمیکنیم
|
||||
elements.push({
|
||||
"@type": "ListItem",
|
||||
position: idx + 1,
|
||||
name: item.name,
|
||||
item: url,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "BreadcrumbList",
|
||||
itemListElement: elements,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user