UNPKG

ap-ssg

Version:

A fast, modular, SEO-optimized static site generator that minifies CSS, JS, and HTML for improved performance. It also supports JSON-LD, sitemap generation, and more, making it ideal for production-ready websites.

202 lines (178 loc) 5.52 kB
const jsonMinify = require("jsonminify"); const { websiteSchema, personSchema } = require("../configs/configObjects"); class JsonldSchemas { /** * @param {Object} doc - The document containing metadata for the schema. */ constructor(doc) { this.doc = doc; } /** * Wraps a schema object in a <script> tag with JSON-LD format. * @param {Object} schemaObject - The schema object to wrap. * @returns {string} - The schema wrapped in a <script> tag. */ wrapSchema(schemaObject) { if (schemaObject === undefined) return ""; const stringify = JSON.stringify(schemaObject); const minifiedSchema = jsonMinify(stringify); return `<script type="application/ld+json">${minifiedSchema}</script>`; } /** * Return AggregateRating object if rating and reviewCount provided else empty object * @param rating * @param reviewCount * @returns {{}|{aggregateRating: {reviewCount, "@type": string, ratingValue}}} */ #getAggregateRating(rating, reviewCount) { if (rating && reviewCount) { return { aggregateRating: { "@type": "AggregateRating", ratingValue: rating, // e.g., 4.5 reviewCount: reviewCount, // e.g., 150 }, }; } return {}; } /** * Return Organization schema if provided * @returns {string} */ getOrganizationSchema() { const { organization } = this.doc; if (!organization) return ""; if (Object.keys(organization).length <= 2) return ""; return this.wrapSchema(organization); } getSoftwareSchema() { const { type } = this.doc; if (type !== "software") return ""; const softwareRepoObjects = this.doc.softwareRepository ? [ { "@type": "PropertyValue", name: "repositoryUrl", value: this.doc.softwareRepository.url, }, { "@type": "PropertyValue", name: "repositoryBranch", value: this.doc.softwareRepository.branch, }, ] : []; const softwarePlatformObj = this.doc.softwarePlatform ? [ { "@type": "PropertyValue", name: "platform", value: this.doc.softwarePlatform, }, ] : []; const schemaJson = { "@context": "https://schema.org", "@type": "SoftwareApplication", name: this.doc.title, description: this.doc.description, url: this.doc.url, version: this.doc.softwareVersion, author: this.doc.author, license: this.doc.softwareLicense, keywords: this.doc.keywords, operatingSystem: this.doc.softwareOperatingSystem, additionalProperty: [...softwarePlatformObj, ...softwareRepoObjects], }; return this.wrapSchema(schemaJson); } getBreadCrumbs() { const { breadCrumbList } = this.doc; if (!Array.isArray(breadCrumbList) || breadCrumbList.length === 0) return ""; const schemaJson = { "@context": "https://schema.org", "@type": "BreadcrumbList", additionalType: "https://schema.org/ItemList", itemListElement: breadCrumbList.map((bc, index) => ({ "@type": "ListItem", position: index + 1, name: bc.name, item: bc.item, })), }; return this.wrapSchema(schemaJson); } getWebsiteSchema() { const { value: validWebsiteSchema, error } = websiteSchema.validate({ url: this.doc.websiteUrl, name: this.doc.websiteName, description: this.doc.websiteDescription, }); if (error) { console.error("Invalid website schema:", error); return ""; // Or return a fallback schema } return this.wrapSchema(validWebsiteSchema); } /** * Generates a Blog schema in JSON-LD format. * @returns {string} - The JSON-LD schema for a blog or an empty string if the type is not "blog". */ getBlogSchema() { const { type, title, description, datePublished, dateCreated, dateModified, author, imageUrl, url, genre, keywords, wordCount, rating, reviewCount, articleSection, editor, inLanguage, isAccessibleForFree, } = this.doc; if (!["article", "blogpost"].includes(type)) return ""; const isBlogPost = type === "blogpost"; const isArticle = type === "article"; const schemaType = isBlogPost ? "BlogPosting" : "Article"; const schemaJson = { "@context": "https://schema.org", "@type": schemaType, headline: title, description, datePublished, dateModified, dateCreated, author, wordCount, url, isAccessibleForFree, inLanguage, image: imageUrl || undefined, mainEntityOfPage: { "@type": "WebPage", "@id": url }, ...this.#getAggregateRating(rating, reviewCount), }; if (isArticle) { schemaJson.section = articleSection; schemaJson.editor = editor; } if (isBlogPost) { schemaJson.genre = genre; schemaJson.keywords = keywords; schemaJson.articleBody = this.doc.articleBody || ""; schemaJson.alternativeHeadline = this.doc.alternativeHeadline || ""; } return this.wrapSchema(schemaJson); } } module.exports = JsonldSchemas;