fix: scope slug generation to each page (#753)

Fixes #34

Luke Karrys committed Oct 13, 2023 at 09:18 UTC 05d227e9f4e3cb826eb18ac9e7c74f90f5d6d231
5 files changed +47 -40
theme/src/components/heading.js
+2 -2
@@ -1,11 +1,11 @@
1 import {Heading, Link} from '@primer/components'
2 import {LinkIcon} from '@primer/octicons-react'
3 import {themeGet} from '@styled-system/theme-get'
4 -import GithubSlugger from 'github-slugger'
4 import React from 'react'
5 import textContent from 'react-addons-text-content'
6 import styled from 'styled-components'
7 import {HEADER_HEIGHT} from './header'
8 +import {useSlugger} from '../use-slugger'
9
10 const StyledHeading = styled(Heading)`
11 margin-top: ${themeGet('space.4')};
@@ -23,7 +23,7 @@ const StyledHeading = styled(Heading)`
23 `
24
25 function MarkdownHeading({children, ...props}) {
26 - const slugger = new GithubSlugger()
26 + const slugger = useSlugger()
27 const text = children ? textContent(children) : ''
28 const id = text ? slugger.slug(text) : ''
29
theme/src/components/hero-layout.js
+25 -22
@@ -6,34 +6,37 @@ import Head from './head'
6 import Header from './header'
7 import Hero from './hero'
8 import Sidebar from './sidebar'
9 +import * as Slugger from '../use-slugger'
10
11 function HeroLayout({children, pageContext, location}) {
12 const {additionalContributors = []} = pageContext.frontmatter
13
14 return (
14 - <Flex flexDirection="column" minHeight="100vh">
15 - <Head />
16 - <Header
17 - location={location}
18 - repositoryUrl={pageContext.repositoryUrl}
19 - isSearchEnabled={pageContext.isSearchEnabled}
20 - />
21 - <Flex flex="1 1 auto" flexDirection="row" role="main">
22 - <Box display={['none', null, null, 'block']}>
23 - <Sidebar repositoryUrl={pageContext.repositoryUrl} location={location} />
24 - </Box>
25 - <Box width="100%">
26 - <Hero />
27 - <Container>
28 - {children}
29 - <PageFooter
30 - editUrl={pageContext.themeOptions.editUrl}
31 - contributors={pageContext.contributors.concat(additionalContributors.map(login => ({login})))}
32 - />
33 - </Container>
34 - </Box>
15 + <Slugger.Provider>
16 + <Flex flexDirection="column" minHeight="100vh">
17 + <Head />
18 + <Header
19 + location={location}
20 + repositoryUrl={pageContext.repositoryUrl}
21 + isSearchEnabled={pageContext.isSearchEnabled}
22 + />
23 + <Flex flex="1 1 auto" flexDirection="row" role="main">
24 + <Box display={['none', null, null, 'block']}>
25 + <Sidebar repositoryUrl={pageContext.repositoryUrl} location={location} />
26 + </Box>
27 + <Box width="100%">
28 + <Hero />
29 + <Container>
30 + {children}
31 + <PageFooter
32 + editUrl={pageContext.themeOptions.editUrl}
33 + contributors={pageContext.contributors.concat(additionalContributors.map(login => ({login})))}
34 + />
35 + </Container>
36 + </Box>
37 + </Flex>
38 </Flex>
36 - </Flex>
39 + </Slugger.Provider>
40 )
41 }
42
theme/src/components/layout.js
+3 -16
@@ -1,15 +1,9 @@
1 import {BorderBox, Box, Flex, Grid, Heading, Position, StyledOcticon, Text} from '@primer/components'
2 import {ChevronDownIcon, ChevronRightIcon} from '@primer/octicons-react'
3 import React from 'react'
4 -import {MDXProvider} from '@mdx-js/react'
4 import Head from './head'
5 import Header, {HEADER_HEIGHT} from './header'
7 -import Index from './index'
8 -import Note from './note'
6 import PageFooter from './page-footer'
10 -import Prompt from './prompt'
11 -import PromptReply from './prompt-reply'
12 -import Screenshot from './screenshot'
7 import Sidebar from './sidebar'
8 import SourceLink from './source-link'
9 import StatusLabel from './status-label'
@@ -17,6 +11,7 @@ import TableOfContents from './table-of-contents'
11 import VariantSelect from './variant-select'
12 import NavHierarchy from '../nav-hierarchy'
13 import Details from './details'
14 +import * as Slugger from '../use-slugger'
15
16 function Layout({children, pageContext, location}) {
17 const {title, description, status, source, additionalContributors = []} = pageContext.frontmatter
@@ -24,15 +19,7 @@ function Layout({children, pageContext, location}) {
19 const variantRoot = NavHierarchy.getVariantRoot(location.pathname)
20
21 return (
27 - <MDXProvider
28 - components={{
29 - Index,
30 - Note,
31 - Prompt,
32 - PromptReply,
33 - Screenshot,
34 - }}
35 - >
22 + <Slugger.Provider>
23 <Flex flexDirection="column" minHeight="100vh">
24 <Head title={title} description={description} />
25 <Header
@@ -133,7 +120,7 @@ function Layout({children, pageContext, location}) {
120 </Grid>
121 </Flex>
122 </Flex>
136 - </MDXProvider>
123 + </Slugger.Provider>
124 )
125 }
126
theme/src/components/wrap-root-element.js
+10
@@ -13,6 +13,11 @@ import InlineCode from './inline-code'
13 import List from './list'
14 import Paragraph from './paragraph'
15 import Table from './table'
16 +import Index from './index'
17 +import Note from './note'
18 +import Prompt from './prompt'
19 +import PromptReply from './prompt-reply'
20 +import Screenshot from './screenshot'
21
22 const components = {
23 a: Link,
@@ -33,6 +38,11 @@ const components = {
38 ul: List,
39 ol: List.withComponent('ol'),
40 dl: DescriptionList,
41 + Index,
42 + Note,
43 + Prompt,
44 + PromptReply,
45 + Screenshot,
46 }
47
48 function wrapRootElement({element}) {
theme/src/use-slugger.js new
+7
@@ -0,0 +1,7 @@
1 +import React from 'react'
2 +import Slugger from 'github-slugger'
3 +
4 +const SluggerContext = React.createContext(null)
5 +
6 +export const Provider = props => <SluggerContext.Provider value={new Slugger()} {...props} />
7 +export const useSlugger = () => React.useContext(SluggerContext)