Use built in gatsby head in favor of react-helmet

Luke Karrys committed Oct 20, 2023 at 17:05 UTC 8c69a786853092db8f9be07622e5c08776444b67
10 files changed +49 -92
content/index.mdx
+1 -1
@@ -1,5 +1,5 @@
1 ---
2 -title: npm Documentation
2 +title: npm Docs
3 edit_on_github: false
4 ---
5
gatsby-config.js
+1 -1
@@ -58,13 +58,13 @@ module.exports = {
58 description: 'Documentation for the npm registry, website, and command-line interface',
59 lang: 'en',
60 imageUrl: 'https://user-images.githubusercontent.com/29712634/81721690-e2fb5d80-9445-11ea-8602-4b2294c964f3.png',
61 + repositoryUrl: 'https://github.com/npm/documentation',
62 },
63 flags: {
64 DEV_SSR: !!process.env.DEV_SSR,
65 },
66 plugins: [
67 'gatsby-plugin-styled-components',
67 - 'gatsby-plugin-react-helmet',
68 'gatsby-transformer-yaml',
69 {
70 resolve: 'gatsby-plugin-mdx',
gatsby-node.js
+5 -5
@@ -1,13 +1,14 @@
1 -const {resolve, join, relative} = require('path')
1 +const {join, relative} = require('path')
2 const {Octokit: CoreOctokit} = require('@octokit/rest')
3 const {throttling} = require('@octokit/plugin-throttling')
4 const {retry} = require('@octokit/plugin-retry')
5
6 const CI = !!process.env.CI
7 +const CWD = process.cwd()
8 +const SRC = join(CWD, 'src')
9 const REPO_URL = 'https://github.com/npm/documentation'
10 const NWO = new URL(REPO_URL).pathname.slice(1)
11 const REPO_BRANCH = 'main'
10 -const CWD = process.cwd()
12 const TEST_CONTRIBUTORS = [
13 {
14 author: {login: 'mona'},
@@ -66,7 +67,7 @@ exports.onCreateWebpackConfig = ({actions}) => {
67 actions.setWebpackConfig({
68 resolve: {
69 alias: {
69 - '~': resolve(__dirname, 'src/'),
70 + '~': SRC,
71 },
72 extensions: ['.js'],
73 },
@@ -172,7 +173,6 @@ const createPage = async (
173 const context = {
174 mdxId: id,
175 tableOfContents: getTableOfConents(tableOfContents),
175 - repositoryUrl: REPO_URL,
176 }
177 // edit_on_github: false in frontmatter will not include editUrl and contributors
178 // on the page. this is used for policy pages as well as some index pages that don't
@@ -184,7 +184,7 @@ const createPage = async (
184
185 actions.createPage({
186 path: pageSlug,
187 - component: contentFilePath,
187 + component: `${join(SRC, 'head.js')}?__contentFilePath=${contentFilePath}`,
188 context,
189 })
190
package-lock.json
-44
@@ -29,7 +29,6 @@
29 "gatsby-plugin-manifest": "^5.12.1",
30 "gatsby-plugin-mdx": "^5.12.1",
31 "gatsby-plugin-meta-redirect": "^1.1.1",
32 - "gatsby-plugin-react-helmet": "^6.12.0",
32 "gatsby-plugin-styled-components": "^6.12.0",
33 "gatsby-source-filesystem": "^5.12.0",
34 "gatsby-transformer-yaml": "^5.12.0",
@@ -41,7 +40,6 @@
40 "react-addons-text-content": "^0.0.4",
41 "react-dom": "^18.2.0",
42 "react-focus-on": "^3.9.1",
44 - "react-helmet": "^6.1.0",
43 "styled-components": "^5.3.11",
44 "styled-system": "^5.1.5"
45 },
@@ -17748,21 +17746,6 @@
17746 "gatsby": "^5.0.0-next"
17747 }
17748 },
17751 - "node_modules/gatsby-plugin-react-helmet": {
17752 - "version": "6.12.0",
17753 - "resolved": "https://registry.npmjs.org/gatsby-plugin-react-helmet/-/gatsby-plugin-react-helmet-6.12.0.tgz",
17754 - "integrity": "sha512-agcBCT9H8nlpkAU3D1fUeJbjh7IMPjGO/njoa7avIYLGsQ2nyGlHwcrEmS2zBHxYKaxPkztvr47OpCdnuEIvEw==",
17755 - "dependencies": {
17756 - "@babel/runtime": "^7.20.13"
17757 - },
17758 - "engines": {
17759 - "node": ">=18.0.0"
17760 - },
17761 - "peerDependencies": {
17762 - "gatsby": "^5.0.0-next",
17763 - "react-helmet": "^5.1.3 || ^6.0.0"
17764 - }
17765 - },
17749 "node_modules/gatsby-plugin-styled-components": {
17750 "version": "6.12.0",
17751 "resolved": "https://registry.npmjs.org/gatsby-plugin-styled-components/-/gatsby-plugin-styled-components-6.12.0.tgz",
@@ -28009,11 +27992,6 @@
27992 "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz",
27993 "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg=="
27994 },
28012 - "node_modules/react-fast-compare": {
28013 - "version": "3.2.2",
28014 - "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz",
28015 - "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ=="
28016 - },
27995 "node_modules/react-focus-lock": {
27996 "version": "2.9.6",
27997 "resolved": "https://registry.npmjs.org/react-focus-lock/-/react-focus-lock-2.9.6.tgz",
@@ -28062,20 +28040,6 @@
28040 }
28041 }
28042 },
28065 - "node_modules/react-helmet": {
28066 - "version": "6.1.0",
28067 - "resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz",
28068 - "integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==",
28069 - "dependencies": {
28070 - "object-assign": "^4.1.1",
28071 - "prop-types": "^15.7.2",
28072 - "react-fast-compare": "^3.1.1",
28073 - "react-side-effect": "^2.1.0"
28074 - },
28075 - "peerDependencies": {
28076 - "react": ">=16.3.0"
28077 - }
28078 - },
28043 "node_modules/react-intersection-observer": {
28044 "version": "9.5.2",
28045 "resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.5.2.tgz",
@@ -28200,14 +28164,6 @@
28164 "node": ">=0.4.0"
28165 }
28166 },
28203 - "node_modules/react-side-effect": {
28204 - "version": "2.1.2",
28205 - "resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.2.tgz",
28206 - "integrity": "sha512-PVjOcvVOyIILrYoyGEpDN3vmYNLdy1CajSFNt4TDsVQC5KpTijDvWVoR+/7Rz2xT978D8/ZtFceXxzsPwZEDvw==",
28207 - "peerDependencies": {
28208 - "react": "^16.3.0 || ^17.0.0 || ^18.0.0"
28209 - }
28210 - },
28167 "node_modules/react-style-singleton": {
28168 "version": "2.2.1",
28169 "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz",
package.json
-2
@@ -44,7 +44,6 @@
44 "gatsby-plugin-manifest": "^5.12.1",
45 "gatsby-plugin-mdx": "^5.12.1",
46 "gatsby-plugin-meta-redirect": "^1.1.1",
47 - "gatsby-plugin-react-helmet": "^6.12.0",
47 "gatsby-plugin-styled-components": "^6.12.0",
48 "gatsby-source-filesystem": "^5.12.0",
49 "gatsby-transformer-yaml": "^5.12.0",
@@ -56,7 +55,6 @@
55 "react-addons-text-content": "^0.0.4",
56 "react-dom": "^18.2.0",
57 "react-focus-on": "^3.9.1",
59 - "react-helmet": "^6.1.0",
58 "styled-components": "^5.3.11",
59 "styled-system": "^5.1.5"
60 },
src/components/nav-items.js
+3 -4
@@ -7,6 +7,7 @@ import * as getNav from '../util/get-nav'
7 import VisuallyHidden from './visually-hidden'
8 import headerNavItems from '../../content/header-nav.yml'
9 import usePage from '../hooks/use-page'
10 +import useSiteMetadata from '../hooks/use-site-metadata'
11
12 const NavItem = ({item, path, depth}) => {
13 const href = getNav.getLocation(item.url)
@@ -53,10 +54,8 @@ const ExternalNavItem = ({title, ...props}) => (
54 )
55
56 const Navigation = () => {
56 - const {
57 - location,
58 - pageContext: {repositoryUrl},
59 - } = usePage()
57 + const {location} = usePage()
58 + const {repositoryUrl} = useSiteMetadata()
59 const path = getNav.getLocation(location.pathname)
60 const items = getNav.getHierarchy(null, {path, hideVariants: true})
61
src/head.js new
+27
@@ -0,0 +1,27 @@
1 +import React from 'react'
2 +import useSiteMetdata from './hooks/use-site-metadata'
3 +
4 +const buildTitle = (...parts) => [...new Set(parts.filter(Boolean))].join(' | ')
5 +
6 +export const Head = ({pageContext: {frontmatter = {}}}) => {
7 + const siteMetadata = useSiteMetdata()
8 +
9 + const title = buildTitle(frontmatter.title, siteMetadata.title)
10 + const description = frontmatter.description || siteMetadata.description
11 +
12 + return (
13 + <>
14 + <title>{title}</title>
15 + <meta name="description" content={description} />
16 + <meta property="og:title" content={title} />
17 + <meta property="og:description" content={description} />
18 + <meta property="og:image" content={siteMetadata.imageUrl} />
19 + <meta property="twitter:card" content="summary_large_image" />
20 + <html lang={siteMetadata.lang} />
21 + </>
22 + )
23 +}
24 +
25 +const PassThrough = ({children}) => children
26 +
27 +export default PassThrough
src/hooks/use-site-metadata.js
+1
@@ -10,6 +10,7 @@ function useSiteMetadata() {
10 description
11 lang
12 imageUrl
13 + repositoryUrl
14 }
15 }
16 }
src/layout.js
+4 -4
@@ -10,7 +10,7 @@ import {SKIP_NAV} from './constants'
10 import useSiteMetadata from './hooks/use-site-metadata'
11 import usePage from './hooks/use-page'
12
13 -export const HeroLayout = ({children}) => {
13 +const HeroLayout = ({children}) => {
14 const {title, description} = useSiteMetadata()
15
16 return (
@@ -32,7 +32,7 @@ export const HeroLayout = ({children}) => {
32 )
33 }
34
35 -export const DefaultLayout = ({children}) => {
35 +const DefaultLayout = ({children}) => {
36 const {title, description} = usePage().frontmatter
37 return (
38 <Box
@@ -62,6 +62,6 @@ export const DefaultLayout = ({children}) => {
62 )
63 }
64
65 -const getLayout = ({path}) => ({'/': HeroLayout})[path] ?? DefaultLayout
65 +const Layout = ({children}) => React.createElement(usePage().path === '/' ? HeroLayout : DefaultLayout, null, children)
66
67 -export default getLayout
67 +export default Layout
src/page.js
+7 -31
@@ -2,34 +2,12 @@ import React from 'react'
2 import {BaseStyles, themeGet, Box} from '@primer/react'
3 import styled, {createGlobalStyle} from 'styled-components'
4 import {SKIP_NAV} from './constants'
5 -import {Helmet} from 'react-helmet'
5 import Slugger from 'github-slugger'
6 import Header from './components/header'
7 import Sidebar from './components/sidebar'
8 import Link from './components/link'
10 -import useSiteMetdata from './hooks/use-site-metadata'
11 -import usePage, {PageProvider} from './hooks/use-page'
12 -import getLayout from './layout'
13 -
14 -const Head = () => {
15 - const {frontmatter} = usePage()
16 - const siteMetadata = useSiteMetdata()
17 -
18 - const title = [frontmatter.title, siteMetadata.title].filter(Boolean).join(' | ')
19 - const description = frontmatter.description || siteMetadata.description
20 -
21 - return (
22 - <Helmet>
23 - <title>{title}</title>
24 - <meta name="description" content={description} />
25 - <meta property="og:title" content={title} />
26 - <meta property="og:description" content={description} />
27 - <meta property="og:image" content={siteMetadata.imageUrl} />
28 - <meta property="twitter:card" content="summary_large_image" />
29 - <html lang={siteMetadata.lang} />
30 - </Helmet>
31 - )
32 -}
9 +import {PageProvider} from './hooks/use-page'
10 +import Layout from './layout'
11
12 const SkipLinkBase = props => (
13 <Link
@@ -46,6 +24,10 @@ const SkipLinkBase = props => (
24 </Link>
25 )
26
27 +// The following rules are to ensure that the element
28 +// is visually hidden, unless it has focus. This is the recommended
29 +// way to hide content from:
30 +// https://webaim.org/techniques/css/invisiblecontent/#techniques
31 export const SkipLink = styled(SkipLinkBase)`
32 z-index: 20;
33 width: auto;
@@ -54,11 +36,6 @@ export const SkipLink = styled(SkipLinkBase)`
36 position: absolute;
37 overflow: hidden;
38
57 - // The following rules are to ensure that the element
58 - // is visually hidden, unless it has focus. This is the recommended
59 - // way to hide content from:
60 - // https://webaim.org/techniques/css/invisiblecontent/#techniques
61 -
39 &:not(:focus) {
40 clip: rect(1px, 1px, 1px, 1px);
41 clip-path: inset(50%);
@@ -90,13 +67,12 @@ const PageElement = ({element, props}) => {
67 <SkipLink />
68 <PageProvider value={page}>
69 <Box sx={{display: 'flex', flexDirection: 'column', minHeight: '100vh'}}>
93 - <Head />
70 <Header />
71 <Box sx={{zIndex: 0, display: 'flex', flex: '1 1 auto', flexDirection: 'row'}} role="main">
72 <Box sx={{display: ['none', null, null, 'block']}}>
73 <Sidebar />
74 </Box>
99 - {React.createElement(getLayout(page), {key: 'layout', ...props}, element)}
75 + <Layout>{element}</Layout>
76 </Box>
77 </Box>
78 </PageProvider>