({ title, children }: SEOProps)
| 44 | } |
| 45 | |
| 46 | const SEO = ({ title, children }: SEOProps) => { |
| 47 | const { t } = useTranslation(); |
| 48 | const { |
| 49 | site: { |
| 50 | siteMetadata: { title: defaultTitle, siteUrl } |
| 51 | } |
| 52 | }: SiteData = useStaticQuery(graphql` |
| 53 | query SEO { |
| 54 | site { |
| 55 | siteMetadata { |
| 56 | title |
| 57 | siteUrl |
| 58 | } |
| 59 | } |
| 60 | } |
| 61 | `); |
| 62 | |
| 63 | const seo = { |
| 64 | title: title || defaultTitle |
| 65 | }; |
| 66 | |
| 67 | const structuredData: StructuredData = { |
| 68 | '@context': 'https://schema.org', |
| 69 | '@type': 'ItemList', |
| 70 | itemListElement: [] |
| 71 | }; |
| 72 | |
| 73 | Object.values(SuperBlocks).forEach((superBlock, index) => { |
| 74 | const superBlockIntroObj: { |
| 75 | title: string; |
| 76 | intro: string[]; |
| 77 | } = t(`intro:${superBlock}`, { returnObjects: true }) as { |
| 78 | title: string; |
| 79 | intro: string[]; |
| 80 | }; |
| 81 | |
| 82 | const { title: i18nTitle, intro: introText } = superBlockIntroObj; |
| 83 | |
| 84 | structuredData.itemListElement.push({ |
| 85 | '@type': 'ListItem', |
| 86 | position: index + 1, |
| 87 | item: { |
| 88 | '@type': 'Course', |
| 89 | url: `${siteUrl}/learn/${superBlock}`, |
| 90 | name: i18nTitle, |
| 91 | description: introText.at(0), |
| 92 | provider: { |
| 93 | '@type': 'Organization', |
| 94 | name: 'freeCodeCamp', |
| 95 | sameAs: 'https://freecodecamp.org', |
| 96 | nonprofitStatus: 'Nonprofit501c3' |
| 97 | } |
| 98 | } |
| 99 | }); |
| 100 | }); |
| 101 | |
| 102 | return ( |
| 103 | <Helmet title={seo.title}> |
nothing calls this directly
no test coverage detected