diff options
| author | Armand Philippot <git@armandphilippot.com> | 2022-05-23 19:02:20 +0200 | 
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2022-05-23 19:02:20 +0200 | 
| commit | 5ebd7c14f7303a0feb8ec1d902ecd0e287d929c3 (patch) | |
| tree | 4e0e0352ac7598fa4e186230e93bcc4c1ac6b810 /src/utils/helpers/schema-org.ts | |
| parent | 34e216546151eaf8a0a3cbb0bc8b65dae4c63bf2 (diff) | |
refactor(schema): use helpers function to avoid repeat between pages
Diffstat (limited to 'src/utils/helpers/schema-org.ts')
| -rw-r--r-- | src/utils/helpers/schema-org.ts | 224 | 
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, +  }; +}; | 
