UNPKG

@paroicms/server

Version:
146 lines 6.9 kB
import { toAbsoluteUrl } from "@paroicms/internal-server-lib"; import { encodeLNodeId } from "@paroicms/public-anywhere-lib"; import { type } from "arktype"; import { getSiteFieldValue } from "../admin-backend/fields/load-fields.queries.js"; import { getHandleOfSiteField } from "../common/media-handles.helpers.js"; import { toMSourceMedia } from "../common/medias/to-media-values.js"; import { truncExcerptToWord } from "../helpers/excerpt.helpers.js"; import { loadOrFromRenderingCache } from "../liquidjs-tools/liquidjs-drop.js"; import { getFeaturedImageOf } from "../rendered-site/helpers/medias.helpers.js"; import { getUrlOfDocument } from "../rendered-site/page-route/make-url.js"; import { getPublicBreadcrumb } from "./breadcrumb.queries.js"; import { loadExcerpt } from "./excerpt.queries.js"; import { loadPublicFieldValues } from "./field-values.js"; import { makeImageAvailable, makeImageAvailableByHandle } from "./make-image-available.js"; const StringOrUndefinedAT = type("string|undefined"); const articleJsonLdTypes = new Set(["Article", "BlogPosting"]); export async function makeJsonLdPayload(renderingContext, documentType, docValues, options) { const { siteContext } = renderingContext; const graph = []; const siteUrl = toAbsoluteUrl(siteContext, "/"); const excerpt = await loadOrFromRenderingCache(renderingContext, `excerpt:${encodeLNodeId(docValues)}:full`, () => loadExcerpt(siteContext, renderingContext.tracker, { lNodeId: docValues, fieldTypes: documentType.fields ?? [], })); const url = options.url ?? (await loadOrFromRenderingCache(renderingContext, `url:${encodeLNodeId(docValues)}`, () => loadUrlOfDocument(renderingContext, docValues))); const siteTitle = await loadOrFromRenderingCache(renderingContext, `siteFields:${docValues.language}:title`, async () => { const title = await getSiteFieldValue(siteContext, { fieldName: "title", language: docValues.language, publishedOnly: true, }); return StringOrUndefinedAT.assert(title); }); const absoluteUrl = toAbsoluteUrl(siteContext, url); const isArticleType = articleJsonLdTypes.has(documentType.jsonLdType ?? ""); const description = excerpt ? truncExcerptToWord(excerpt, 160) : docValues.metaDescription ? truncExcerptToWord(docValues.metaDescription, 160) : undefined; const pageEntity = { "@type": documentType.jsonLdType ?? "WebPage", "@id": `${absoluteUrl}/#webpage`, url: absoluteUrl, inLanguage: docValues.language, isPartOf: { "@id": `${siteUrl}#website` }, }; if (isArticleType) { pageEntity.headline = docValues.title; } else { pageEntity.name = docValues.title; } if (description) pageEntity.description = description; if (docValues.publishDate) pageEntity.datePublished = docValues.publishDate; if (docValues.updatedAt) pageEntity.dateModified = docValues.updatedAt; if (isArticleType) { const featuredImageId = await loadOrFromRenderingCache(renderingContext, `featuredImage:${encodeLNodeId(docValues)}`, async () => (await getFeaturedImageOf(renderingContext, { nodeId: docValues.nodeId, documentType, }))?.id); if (featuredImageId !== undefined) { const ogMedia = await siteContext.mediaStorage.getMedia({ mediaId: featuredImageId }); if (ogMedia?.kind === "image") { const imageVariant = await makeImageAvailable(renderingContext, toMSourceMedia(siteContext, ogMedia), { pixelRatio: 1, resizeRule: "1200x630" }); pageEntity.image = { "@type": "ImageObject", url: toAbsoluteUrl(siteContext, imageVariant.url), width: imageVariant.rawWidth, height: imageVariant.rawHeight, }; } } const authorsField = documentType.fields?.find((f) => f.dataType === "labeling" && f.storedAs === "labeling" && f.taxonomy === "author"); if (authorsField) { const fieldValues = await loadPublicFieldValues(renderingContext, { typeName: docValues.type, lNodeId: docValues, fieldNames: [authorsField.name], }); const authorTerms = fieldValues && typeof fieldValues === "object" ? fieldValues[authorsField.name] : undefined; if (authorTerms && Array.isArray(authorTerms) && authorTerms.length > 0) { pageEntity.author = authorTerms.map((term) => { const entry = { "@type": "Person", name: term.title }; if (term.url) entry.url = toAbsoluteUrl(siteContext, term.url); return entry; }); } } const publisher = { "@type": "Organization", name: siteTitle }; const logoHandle = getHandleOfSiteField(siteContext, { fieldName: "logo" }); const logoImage = await makeImageAvailableByHandle(renderingContext, { handle: logoHandle }, { resizeRule: "x112x", pixelRatio: 1 }); if (logoImage) { publisher.logo = { "@type": "ImageObject", url: toAbsoluteUrl(siteContext, logoImage.url), width: logoImage.rawWidth, height: logoImage.rawHeight, }; } pageEntity.publisher = publisher; } graph.push(pageEntity); const breadcrumbItems = await loadOrFromRenderingCache(renderingContext, `breadcrumb:${encodeLNodeId(docValues)}`, () => getPublicBreadcrumb(renderingContext, docValues)); const listItems = breadcrumbItems .filter((item) => item.url) .map((item, index) => ({ "@type": "ListItem", position: index + 1, name: item.title ?? "", item: toAbsoluteUrl(siteContext, item.url), })); if (listItems.length > 0) { graph.push({ "@type": "BreadcrumbList", itemListElement: listItems, }); } if (documentType.typeName === "home") { graph.push({ "@type": "WebSite", "@id": `${siteUrl}#website`, name: siteTitle, url: siteUrl, inLanguage: docValues.language, }); } return graph; } async function loadUrlOfDocument(renderingContext, documentId) { const { siteContext } = renderingContext; const { url, dependencyKeys } = await getUrlOfDocument(siteContext, renderingContext.tracker, documentId, { returnUrlDependencyKeys: true, forPreview: renderingContext.isPreview, }); renderingContext.addDependencyKey(...dependencyKeys); return url; } //# sourceMappingURL=json-ld-payload.js.map