File: //var/www/quadcode.com/src/lib/scheme/schemaUnified.ts
import { decodeBasicHtmlEntities } from '$utils/decodeBasicHtmlEntities';
import type { IPost } from '$type/post';
import type {
FAQItem,
ArticleItem,
FAQPage,
VideoObject,
Article,
WebPageSchema,
UnifiedSchemaProps,
BreadcrumbList,
} from './types';
import { PUBLIC_SITE_NAME } from '$env/static/public';
export function transformPostToArticleItem(post: IPost): ArticleItem {
return {
name: post.title.rendered,
description: post.yoast_head_json.og_description,
image: post.imageData.large,
author: {
name: post.authorData.name,
description: post.authorData.description,
position: post.authorData.position,
},
headline: post.title.rendered,
about: post.yoast_head_json.og_description,
url: post.link,
};
}
export function generateUnifiedSchema({
title,
description,
faqItems = [],
videoItems = [],
articles = [],
singleArticle,
howToItem,
breadcrumb = [],
}: UnifiedSchemaProps): string {
const webPageSchema: WebPageSchema = {
'@context': 'https://schema.org',
'@graph': [],
};
if (title && description) {
webPageSchema['@graph'].push({
'@type': 'WebPage',
name: decodeBasicHtmlEntities(title),
description: decodeBasicHtmlEntities(description),
});
}
if (faqItems && faqItems.length > 0) {
const faqPage: FAQPage = {
'@type': 'FAQPage',
mainEntity: faqItems.map((item: FAQItem) => ({
'@type': 'Question',
name: decodeBasicHtmlEntities(item.question),
acceptedAnswer: {
'@type': 'Answer',
text: decodeBasicHtmlEntities(item.answer),
},
})),
};
webPageSchema['@graph'].push(faqPage);
}
if (videoItems && videoItems.length > 0) {
videoItems.forEach((video) => {
const videoPage: VideoObject = {
'@type': 'VideoObject',
name: decodeBasicHtmlEntities(video.name),
description: decodeBasicHtmlEntities(video.description),
thumbnailUrl: video.thumbnailUrl,
contentUrl: video.contentUrl,
};
if (video.uploadDate) {
videoPage.uploadDate = video.uploadDate;
}
webPageSchema['@graph'].push(videoPage);
});
}
if (articles && articles.length > 0) {
articles.forEach((article) => {
const articleSchema: Article = {
'@type': 'Article',
name: decodeBasicHtmlEntities(article.name),
description: decodeBasicHtmlEntities(article.description),
image: article.image,
author: {
'@type': 'Person',
name: decodeBasicHtmlEntities(article.author.name),
description: article.author.description ? decodeBasicHtmlEntities(article.author.description) : undefined,
jobTitle: article.author.position ? decodeBasicHtmlEntities(article.author.position) : undefined,
},
headline: decodeBasicHtmlEntities(article.headline),
about: decodeBasicHtmlEntities(article.about),
url: article.url,
};
webPageSchema['@graph'].push(articleSchema);
});
}
if (singleArticle) {
const articleSchema: Article = {
'@type': 'Article',
name: decodeBasicHtmlEntities(singleArticle.name),
description: decodeBasicHtmlEntities(singleArticle.description),
image: singleArticle.image,
author: {
'@type': 'Person',
name: decodeBasicHtmlEntities(singleArticle.author.name),
description: singleArticle.author.description
? decodeBasicHtmlEntities(singleArticle.author.description)
: undefined,
jobTitle: singleArticle.author.position ? decodeBasicHtmlEntities(singleArticle.author.position) : undefined,
},
headline: decodeBasicHtmlEntities(singleArticle.headline),
about: decodeBasicHtmlEntities(singleArticle.about),
url: singleArticle.url,
};
webPageSchema['@graph'].push(articleSchema);
}
if (howToItem) {
const articleSchema: Article = {
'@type': 'Article',
name: decodeBasicHtmlEntities(howToItem.name),
description: decodeBasicHtmlEntities(howToItem.description),
image: howToItem.image,
author: {
'@type': 'Person',
name: decodeBasicHtmlEntities(howToItem.author.name),
description: howToItem.author.description ? decodeBasicHtmlEntities(howToItem.author.description) : undefined,
jobTitle: howToItem.author.position ? decodeBasicHtmlEntities(howToItem.author.position) : undefined,
},
headline: decodeBasicHtmlEntities(howToItem.headline),
about: decodeBasicHtmlEntities(howToItem.about),
url: howToItem.url,
};
webPageSchema['@graph'].push(articleSchema);
}
if (breadcrumb && breadcrumb.length > 0) {
const breadcrumbList: BreadcrumbList['itemListElement'] = [
{
'@type': 'ListItem',
position: 1,
name: 'Home',
item: PUBLIC_SITE_NAME,
},
];
breadcrumb.forEach((item, index) => {
const path = item.tree[item.tree.length - 1]?.path || '';
breadcrumbList.push({
'@type': 'ListItem',
position: index + 2,
name: item.title,
item: `${PUBLIC_SITE_NAME}/${path}`,
});
});
webPageSchema['@graph'].push({
'@type': 'BreadcrumbList',
itemListElement: breadcrumbList,
});
}
return JSON.stringify(webPageSchema, null, 2);
}
export function getUnifiedSchemaScript(props: UnifiedSchemaProps): string {
const schemaContent = generateUnifiedSchema(props);
return `<script id="schema-org" type="application/ld+json" data-nscript="beforeInteractive">${schemaContent}</script>`;
}