aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/templates
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2023-12-14 15:30:34 +0100
committerArmand Philippot <git@armandphilippot.com>2023-12-14 16:30:04 +0100
commit7063b199b4748a9c354ed37e64cdc84c512f2c0c (patch)
tree7506c3003c56b49a248e9adb40be610780bb540e /src/components/templates
parent85c4c42bd601270d7be0f34a0767a34bb85e29bb (diff)
refactor(pages): rewrite helpers to output schema in json-ld format
* make sure url are absolutes * nest breadcrumb schema in webpage schema * trim HTML tags from content/description * use a regular script instead of next/script (with the latter the schema is not updated on route change) * place the script in document head * add keywords, wordCount and readingTime keys in BlogPosting schema * fix breadcrumbs in search page (without query) * add tests (a `MatchInlineSnapshot` will be better but Prettier 3 is not supported yet)
Diffstat (limited to 'src/components/templates')
-rw-r--r--src/components/templates/layout/layout.tsx47
-rw-r--r--src/components/templates/layout/site-header/site-header.tsx7
-rw-r--r--src/components/templates/page/page-comments.tsx5
-rw-r--r--src/components/templates/page/page.tsx5
4 files changed, 13 insertions, 51 deletions
diff --git a/src/components/templates/layout/layout.tsx b/src/components/templates/layout/layout.tsx
index 4dfe5f3..2a6ac2e 100644
--- a/src/components/templates/layout/layout.tsx
+++ b/src/components/templates/layout/layout.tsx
@@ -1,19 +1,11 @@
-import Script from 'next/script';
import type { FC, ReactElement, ReactNode } from 'react';
import { useIntl } from 'react-intl';
-import type { Person, SearchAction, WebSite, WithContext } from 'schema-dts';
import type { NextPageWithLayoutOptions } from '../../../types';
-import { CONFIG } from '../../../utils/config';
-import { ROUTES } from '../../../utils/constants';
import { ButtonLink, Main } from '../../atoms';
import styles from './layout.module.scss';
import { SiteFooter } from './site-footer';
import { SiteHeader, type SiteHeaderProps } from './site-header';
-export type QueryAction = SearchAction & {
- 'query-input': string;
-};
-
export type LayoutProps = Pick<SiteHeaderProps, 'isHome'> & {
/**
* The layout main content.
@@ -27,7 +19,6 @@ export type LayoutProps = Pick<SiteHeaderProps, 'isHome'> & {
* Render the base layout used by all pages.
*/
export const Layout: FC<LayoutProps> = ({ children, isHome }) => {
- const { baseline, copyright, locales, name, url } = CONFIG;
const intl = useIntl();
const messages = {
noScript: intl.formatMessage({
@@ -43,49 +34,11 @@ export const Layout: FC<LayoutProps> = ({ children, isHome }) => {
}),
};
- const searchActionSchema: QueryAction = {
- '@type': 'SearchAction',
- target: {
- '@type': 'EntryPoint',
- urlTemplate: `${url}${ROUTES.SEARCH}?s={search_term_string}`,
- },
- query: 'required',
- 'query-input': 'required name=search_term_string',
- };
- const brandingSchema: Person = {
- '@type': 'Person',
- name,
- url,
- jobTitle: baseline,
- image: '/armand-philippot.jpg',
- subjectOf: { '@id': `${url}` },
- };
- const schemaJsonLd: WithContext<WebSite> = {
- '@context': 'https://schema.org',
- '@id': `${url}`,
- '@type': 'WebSite',
- name,
- description: baseline,
- url,
- author: brandingSchema,
- copyrightYear: Number(copyright.startYear),
- creator: brandingSchema,
- editor: brandingSchema,
- inLanguage: locales.defaultLocale,
- potentialAction: searchActionSchema,
- };
-
const topId = 'top';
const mainId = 'main';
return (
<>
- <Script
- dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaJsonLd) }}
- // eslint-disable-next-line react/jsx-no-literals -- Id allowed
- id="schema-layout"
- type="application/ld+json"
- />
<span id={topId} />
<noscript>
<div className={styles['noscript-spacing']} />
diff --git a/src/components/templates/layout/site-header/site-header.tsx b/src/components/templates/layout/site-header/site-header.tsx
index 3e06350..91add77 100644
--- a/src/components/templates/layout/site-header/site-header.tsx
+++ b/src/components/templates/layout/site-header/site-header.tsx
@@ -1,4 +1,5 @@
import { type ForwardRefRenderFunction, forwardRef } from 'react';
+import { AUTHOR_ID } from '../../../../utils/constants';
import { Header, type HeaderProps } from '../../../atoms';
import { SiteBranding } from './site-branding';
import styles from './site-header.module.scss';
@@ -16,7 +17,11 @@ const SiteHeaderWithRef: ForwardRefRenderFunction<
return (
<Header {...props} className={headerClass} ref={ref}>
- <SiteBranding className={styles.branding} isHome={isHome} />
+ <SiteBranding
+ className={styles.branding}
+ id={AUTHOR_ID}
+ isHome={isHome}
+ />
<SiteNavbar className={styles.navbar} />
</Header>
);
diff --git a/src/components/templates/page/page-comments.tsx b/src/components/templates/page/page-comments.tsx
index 5f5208f..01c4eea 100644
--- a/src/components/templates/page/page-comments.tsx
+++ b/src/components/templates/page/page-comments.tsx
@@ -10,6 +10,7 @@ import {
createComment,
type CreateCommentInput,
} from '../../../services/graphql';
+import { COMMENTS_SECTION_ID } from '../../../utils/constants';
import { Heading, Link, Section } from '../../atoms';
import { Card, CardBody } from '../../molecules';
import {
@@ -27,7 +28,7 @@ const link = (chunks: ReactNode) => (
export type PageCommentsProps = Omit<
HTMLAttributes<HTMLDivElement>,
- 'children' | 'onSubmit'
+ 'children' | 'id' | 'onSubmit'
> &
Pick<CommentsListProps, 'depth'> & {
/**
@@ -139,7 +140,7 @@ const PageCommentsWithRef: ForwardRefRenderFunction<
);
return (
- <div {...props} className={wrapperClass} ref={ref}>
+ <div {...props} className={wrapperClass} id={COMMENTS_SECTION_ID} ref={ref}>
<Section className={styles.comments__body}>
<Heading className={styles.heading} level={2}>
{commentsListTitle}
diff --git a/src/components/templates/page/page.tsx b/src/components/templates/page/page.tsx
index b40c2f9..e3a4453 100644
--- a/src/components/templates/page/page.tsx
+++ b/src/components/templates/page/page.tsx
@@ -4,6 +4,7 @@ import {
type HTMLAttributes,
} from 'react';
import { useIntl } from 'react-intl';
+import { ARTICLE_ID } from '../../../utils/constants';
import { Article } from '../../atoms';
import { Breadcrumbs, type BreadcrumbsItem } from '../../organisms/nav';
import styles from './page.module.scss';
@@ -63,7 +64,9 @@ const PageWithRef: ForwardRefRenderFunction<HTMLDivElement, PageProps> = (
items={breadcrumbs}
/>
) : null}
- <Article className={pageClass}>{children}</Article>
+ <Article className={pageClass} id={ARTICLE_ID}>
+ {children}
+ </Article>
</div>
);
};