summaryrefslogtreecommitdiffstats
path: root/src/utils/helpers/schema-org.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/utils/helpers/schema-org.ts')
-rw-r--r--src/utils/helpers/schema-org.ts224
1 files changed, 224 insertions, 0 deletions
diff --git a/src/utils/helpers/schema-org.ts b/src/utils/helpers/schema-org.ts
new file mode 100644
index 0000000..cdace00
--- /dev/null
+++ b/src/utils/helpers/schema-org.ts
@@ -0,0 +1,224 @@
+import { Dates } from '@ts/types/app';
+import { settings } from '@utils/config';
+import {
+ AboutPage,
+ Article,
+ Blog,
+ BlogPosting,
+ ContactPage,
+ Graph,
+ WebPage,
+} from 'schema-dts';
+
+export type GetBlogSchemaProps = {
+ /**
+ * True if the page is part of the blog.
+ */
+ isSinglePage: boolean;
+ /**
+ * The page locale.
+ */
+ locale: string;
+ /**
+ * The page slug with a leading slash.
+ */
+ slug: string;
+};
+
+/**
+ * Retrieve the JSON for Blog schema.
+ *
+ * @param props - The page data.
+ * @returns {Blog} The JSON for Blog schema.
+ */
+export const getBlogSchema = ({
+ isSinglePage,
+ locale,
+ slug,
+}: GetBlogSchemaProps): Blog => {
+ return {
+ '@id': `${settings.url}/#blog`,
+ '@type': 'Blog',
+ author: { '@id': `${settings.url}/#branding` },
+ creator: { '@id': `${settings.url}/#branding` },
+ editor: { '@id': `${settings.url}/#branding` },
+ blogPost: isSinglePage ? { '@id': `${settings.url}/#article` } : undefined,
+ inLanguage: locale,
+ isPartOf: isSinglePage
+ ? {
+ '@id': `${settings.url}${slug}`,
+ }
+ : undefined,
+ license: 'https://creativecommons.org/licenses/by-sa/4.0/deed.fr',
+ mainEntityOfPage: isSinglePage
+ ? undefined
+ : { '@id': `${settings.url}${slug}` },
+ };
+};
+
+export type SinglePageSchemaReturn = {
+ about: AboutPage;
+ contact: ContactPage;
+ page: Article;
+ post: BlogPosting;
+};
+
+export type SinglePageSchemaKind = keyof SinglePageSchemaReturn;
+
+export type GetSinglePageSchemaProps<T extends SinglePageSchemaKind> = {
+ /**
+ * The number of comments.
+ */
+ commentsCount?: number;
+ /**
+ * The page content.
+ */
+ content?: string;
+ /**
+ * The url of the cover.
+ */
+ cover?: string;
+ /**
+ * The page dates.
+ */
+ dates: Dates;
+ /**
+ * The page description.
+ */
+ description: string;
+ /**
+ * The page id.
+ */
+ id: string;
+ /**
+ * The page kind.
+ */
+ kind: T;
+ /**
+ * The page locale.
+ */
+ locale: string;
+ /**
+ * The page slug with a leading slash.
+ */
+ slug: string;
+ /**
+ * The page title.
+ */
+ title: string;
+};
+
+/**
+ * Retrieve the JSON schema depending on the page kind.
+ *
+ * @param props - The page data.
+ * @returns {SinglePageSchemaReturn[T]} - Either AboutPage, ContactPage, Article or BlogPosting schema.
+ */
+export const getSinglePageSchema = <T extends SinglePageSchemaKind>({
+ commentsCount,
+ content,
+ cover,
+ dates,
+ description,
+ id,
+ kind,
+ locale,
+ title,
+ slug,
+}: GetSinglePageSchemaProps<T>): SinglePageSchemaReturn[T] => {
+ const publicationDate = new Date(dates.publication);
+ const updateDate = dates.update ? new Date(dates.update) : undefined;
+ const singlePageSchemaType = {
+ about: 'AboutPage',
+ contact: 'ContactPage',
+ page: 'Article',
+ post: 'BlogPosting',
+ };
+
+ return {
+ '@id': `${settings.url}/#${id}`,
+ '@type': singlePageSchemaType[kind],
+ name: title,
+ description,
+ articleBody: content,
+ author: { '@id': `${settings.url}/#branding` },
+ commentCount: commentsCount,
+ copyrightYear: publicationDate.getFullYear(),
+ creator: { '@id': `${settings.url}/#branding` },
+ dateCreated: publicationDate.toISOString(),
+ dateModified: updateDate && updateDate.toISOString(),
+ datePublished: publicationDate.toISOString(),
+ editor: { '@id': `${settings.url}/#branding` },
+ headline: title,
+ image: cover,
+ inLanguage: locale,
+ license: 'https://creativecommons.org/licenses/by-sa/4.0/deed.fr',
+ thumbnailUrl: cover,
+ isPartOf:
+ kind === 'post'
+ ? {
+ '@id': `${settings.url}/blog`,
+ }
+ : undefined,
+ mainEntityOfPage: { '@id': `${settings.url}${slug}` },
+ } as SinglePageSchemaReturn[T];
+};
+
+export type GetWebPageSchemaProps = {
+ /**
+ * The page description.
+ */
+ description: string;
+ /**
+ * The page locale.
+ */
+ locale: string;
+ /**
+ * The page slug.
+ */
+ slug: string;
+ /**
+ * The page title.
+ */
+ title: string;
+ /**
+ * The page last update.
+ */
+ updateDate?: string;
+};
+
+/**
+ * Retrieve the JSON for WebPage schema.
+ *
+ * @param props - The page data.
+ * @returns {WebPage} The JSON for WebPage schema.
+ */
+export const getWebPageSchema = ({
+ description,
+ locale,
+ slug,
+ title,
+ updateDate,
+}: GetWebPageSchemaProps): WebPage => {
+ return {
+ '@id': `${settings.url}${slug}`,
+ '@type': 'WebPage',
+ breadcrumb: { '@id': `${settings.url}/#breadcrumb` },
+ lastReviewed: updateDate,
+ name: title,
+ description: description,
+ inLanguage: locale,
+ reviewedBy: { '@id': `${settings.url}/#branding` },
+ url: `${settings.url}${slug}`,
+ isPartOf: {
+ '@id': `${settings.url}`,
+ },
+ };
+};
+
+export const getSchemaJson = (graphs: Graph['@graph']): Graph => {
+ return {
+ '@context': 'https://schema.org',
+ '@graph': graphs,
+ };
+};