@asgerami/zemenay-blog
Version:
Plug-and-play blog system for Next.js - Get a fully functional blog running in minutes with zero configuration
132 lines (131 loc) • 4.17 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateSEOFromPost = generateSEOFromPost;
exports.extractDescription = extractDescription;
exports.generateMetaTags = generateMetaTags;
exports.generateStructuredData = generateStructuredData;
const imageUpload_1 = require("./imageUpload");
/**
* Generate SEO data from a blog post
*/
function generateSEOFromPost(post, baseUrl) {
// Extract description from content (first 160 characters, strip HTML)
const description = extractDescription(post.content);
// Get featured image URL if available
const image = post.featured_image
? (0, imageUpload_1.getImageUrl)(post.featured_image.file_path)
: undefined;
// Generate full URL if baseUrl provided
const url = baseUrl ? `${baseUrl}/blog/${post.slug}` : undefined;
return {
title: post.title,
description,
image,
url,
type: "article",
publishedTime: post.created_at,
modifiedTime: post.updated_at,
author: "Blog Author", // You can customize this
};
}
/**
* Extract a clean description from HTML content
*/
function extractDescription(htmlContent, maxLength = 160) {
// Remove HTML tags
const textContent = htmlContent.replace(/<[^>]*>/g, "");
// Clean up whitespace
const cleanText = textContent.replace(/\s+/g, " ").trim();
// Truncate to maxLength
if (cleanText.length <= maxLength) {
return cleanText;
}
// Find the last complete word within the limit
const truncated = cleanText.substring(0, maxLength);
const lastSpaceIndex = truncated.lastIndexOf(" ");
if (lastSpaceIndex > 0) {
return truncated.substring(0, lastSpaceIndex) + "...";
}
return truncated + "...";
}
/**
* Generate meta tags for SEO
*/
function generateMetaTags(seoData) {
const tags = {
title: seoData.title,
description: seoData.description,
};
// Open Graph tags
tags["og:title"] = seoData.title;
tags["og:description"] = seoData.description;
tags["og:type"] = seoData.type || "website";
if (seoData.url) {
tags["og:url"] = seoData.url;
}
if (seoData.image) {
tags["og:image"] = seoData.image;
tags["og:image:alt"] = seoData.title;
}
// Twitter Card tags
tags["twitter:card"] = "summary_large_image";
tags["twitter:title"] = seoData.title;
tags["twitter:description"] = seoData.description;
if (seoData.image) {
tags["twitter:image"] = seoData.image;
}
// Article-specific tags
if (seoData.type === "article") {
if (seoData.publishedTime) {
tags["article:published_time"] = seoData.publishedTime;
}
if (seoData.modifiedTime) {
tags["article:modified_time"] = seoData.modifiedTime;
}
if (seoData.author) {
tags["article:author"] = seoData.author;
}
}
return tags;
}
/**
* Generate JSON-LD structured data
*/
function generateStructuredData(seoData, baseUrl) {
const structuredData = {
"@context": "https://schema.org",
"@type": seoData.type === "article" ? "BlogPosting" : "WebPage",
headline: seoData.title,
description: seoData.description,
};
if (seoData.url) {
structuredData.url = seoData.url;
}
if (seoData.image) {
structuredData.image = {
"@type": "ImageObject",
url: seoData.image,
};
}
if (seoData.type === "article") {
if (seoData.publishedTime) {
structuredData.datePublished = seoData.publishedTime;
}
if (seoData.modifiedTime) {
structuredData.dateModified = seoData.modifiedTime;
}
if (seoData.author) {
structuredData.author = {
"@type": "Person",
name: seoData.author,
};
}
// Add publisher info (customize as needed)
structuredData.publisher = {
"@type": "Organization",
name: "Zemenay Blog",
url: baseUrl || "",
};
}
return structuredData;
}