mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 10:22:16 +00:00
117 lines
2.3 KiB
TypeScript
117 lines
2.3 KiB
TypeScript
import { useStaticQuery, graphql } from 'gatsby';
|
|
import React from 'react';
|
|
import Helmet from 'react-helmet';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { SuperBlocks } from '@freecodecamp/shared/config/curriculum';
|
|
|
|
interface SEOProps {
|
|
title?: string;
|
|
}
|
|
|
|
interface SiteData {
|
|
site: {
|
|
siteMetadata: {
|
|
title: string;
|
|
siteUrl: string;
|
|
};
|
|
};
|
|
}
|
|
|
|
interface Item {
|
|
'@type': 'Course';
|
|
url: string;
|
|
name: string;
|
|
description?: string;
|
|
provider: {
|
|
'@type': 'Organization';
|
|
name: string;
|
|
sameAs: string;
|
|
nonprofitStatus: string;
|
|
};
|
|
}
|
|
|
|
export interface ListItem {
|
|
'@type': 'ListItem';
|
|
position: number;
|
|
item: Item;
|
|
}
|
|
|
|
interface StructuredData {
|
|
'@context': string;
|
|
'@type': string;
|
|
itemListElement: ListItem[];
|
|
}
|
|
|
|
const SEO: React.FC<SEOProps> = ({ title, children }) => {
|
|
const { t } = useTranslation();
|
|
const {
|
|
site: {
|
|
siteMetadata: { title: defaultTitle, siteUrl }
|
|
}
|
|
}: SiteData = useStaticQuery(graphql`
|
|
query SEO {
|
|
site {
|
|
siteMetadata {
|
|
title
|
|
siteUrl
|
|
}
|
|
}
|
|
}
|
|
`);
|
|
|
|
const seo = {
|
|
title: title || defaultTitle
|
|
};
|
|
|
|
const structuredData: StructuredData = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'ItemList',
|
|
itemListElement: []
|
|
};
|
|
|
|
Object.values(SuperBlocks).forEach((superBlock, index) => {
|
|
const superBlockIntroObj: {
|
|
title: string;
|
|
intro: string[];
|
|
} = t(`intro:${superBlock}`, { returnObjects: true }) as {
|
|
title: string;
|
|
intro: string[];
|
|
};
|
|
|
|
const { title: i18nTitle, intro: introText } = superBlockIntroObj;
|
|
|
|
structuredData.itemListElement.push({
|
|
'@type': 'ListItem',
|
|
position: index + 1,
|
|
item: {
|
|
'@type': 'Course',
|
|
url: `${siteUrl}/learn/${superBlock}`,
|
|
name: i18nTitle,
|
|
description: introText.at(0),
|
|
provider: {
|
|
'@type': 'Organization',
|
|
name: 'freeCodeCamp',
|
|
sameAs: 'https://freecodecamp.org',
|
|
nonprofitStatus: 'Nonprofit501c3'
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
return (
|
|
<Helmet title={seo.title}>
|
|
<script
|
|
type='application/ld+json'
|
|
data-playwright-test-label='structured-data'
|
|
>
|
|
{JSON.stringify(structuredData)}
|
|
</script>
|
|
{children}
|
|
</Helmet>
|
|
);
|
|
};
|
|
|
|
SEO.displayName = 'SEO';
|
|
|
|
export default SEO;
|