mirror of https://github.com/ethereum/go-ethereum
Create docs navigation sidebar (#40)
* crawl files and create directory tree for sidebar * dropdown * Working on dropdown links and styling * setup header nav * Styles * DocumentNav sidebar done * wrap up header sidebar * setup top level nav * update root level data and fix link bug * doc links yaml * nav links for docs * remove character * prettier * fix build error * MDX style * Update src/components/UI/docs/DocsLinks.tsx Co-authored-by: Paul Wackerow <54227730+wackerow@users.noreply.github.com> * Abstract LinksList component into its own file * change requests * AccordionButton styles * AccordionButton styled * fix broken links * prettier * prettier * fix broken default code snippet * fix accordion spacing * fix gap at top of DocsNav lg * fix but of persistent header link * remove test content * setup Notes and prettier * rehype * Note component * Note font styling * convert old notes to use component * Breadcrumb cleanup and prettier * MDXComponents -> MDComponent and documentation Co-authored-by: Paul Wackerow <54227730+wackerow@users.noreply.github.com>pull/26459/head^2
parent
fc52cc75e4
commit
0b9ff8b1e6
@ -1,114 +0,0 @@ |
||||
import { |
||||
Flex, |
||||
Heading, |
||||
Link, |
||||
ListItem, |
||||
OrderedList, |
||||
Stack, |
||||
Table, |
||||
Text, |
||||
UnorderedList |
||||
} from '@chakra-ui/react'; |
||||
import NextLink from 'next/link'; |
||||
|
||||
import { Code } from './UI/docs'; |
||||
import { textStyles } from '../theme/foundations'; |
||||
|
||||
const { header1, header2, header3, header4 } = textStyles; |
||||
|
||||
const MDXComponents = { |
||||
// paragraphs
|
||||
p: ({ children }: any) => { |
||||
return ( |
||||
<Text mb={7} lineHeight={1.5}> |
||||
{children} |
||||
</Text> |
||||
); |
||||
}, |
||||
// links
|
||||
a: ({ children, href }: any) => { |
||||
return ( |
||||
<NextLink href={href} passHref> |
||||
<Link |
||||
isExternal={href.startsWith('http') && !href.includes('geth.ethereum.org')} |
||||
variant='light' |
||||
> |
||||
{children} |
||||
</Link> |
||||
</NextLink> |
||||
); |
||||
}, |
||||
// headings
|
||||
h1: ({ children }: any) => { |
||||
return ( |
||||
<Heading as='h1' textAlign='start' mb={5} {...header1}> |
||||
{children} |
||||
</Heading> |
||||
); |
||||
}, |
||||
h2: ({ children }: any) => { |
||||
return ( |
||||
<Heading as='h2' textAlign='start' mt='16 !important' mb={4} {...header2}> |
||||
{children} |
||||
</Heading> |
||||
); |
||||
}, |
||||
h3: ({ children }: any) => { |
||||
return ( |
||||
<Heading as='h3' mt={5} mb={2.5} {...header3}> |
||||
{children} |
||||
</Heading> |
||||
); |
||||
}, |
||||
h4: ({ children }: any) => { |
||||
return ( |
||||
<Heading as='h4' mb={2.5} {...header4}> |
||||
{children} |
||||
</Heading> |
||||
); |
||||
}, |
||||
// tables
|
||||
table: ({ children }: any) => ( |
||||
<Flex maxW='min(100%, 100vw)' overflowX='scroll'> |
||||
<Table |
||||
variant='striped' |
||||
colorScheme='greenAlpha' |
||||
border='1px' |
||||
borderColor='blackAlpha.50' |
||||
my={6} |
||||
size={{ base: 'sm', lg: 'md' }} |
||||
w='auto' |
||||
> |
||||
{children} |
||||
</Table> |
||||
</Flex> |
||||
), |
||||
// pre
|
||||
pre: ({ children }: any) => ( |
||||
<Stack mb={5}> |
||||
<pre>{children}</pre> |
||||
</Stack> |
||||
), |
||||
// code
|
||||
code: ({ children, ...props }: any) => <Code {...props}>{children}</Code>, |
||||
// list
|
||||
ul: ({ children }: any) => { |
||||
return ( |
||||
<UnorderedList mb={7} px={4}> |
||||
{children} |
||||
</UnorderedList> |
||||
); |
||||
}, |
||||
ol: ({ children }: any) => { |
||||
return ( |
||||
<OrderedList mb={7} px={4}> |
||||
{children} |
||||
</OrderedList> |
||||
); |
||||
}, |
||||
li: ({ children }: any) => { |
||||
return <ListItem color='primary'>{children}</ListItem>; |
||||
} |
||||
}; |
||||
|
||||
export default MDXComponents; |
@ -0,0 +1,33 @@ |
||||
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, Stack } from '@chakra-ui/react'; |
||||
import NextLink from 'next/link'; |
||||
import { useRouter } from 'next/router'; |
||||
import { FC } from 'react'; |
||||
|
||||
export const Breadcrumbs: FC = () => { |
||||
const router = useRouter(); |
||||
|
||||
let pathSplit = router.asPath.split('/'); |
||||
pathSplit = pathSplit.splice(1, pathSplit.length); |
||||
|
||||
return ( |
||||
<> |
||||
{router.asPath !== '/docs' ? ( |
||||
<Breadcrumb> |
||||
{pathSplit.map((path: string, idx: number) => { |
||||
return ( |
||||
<BreadcrumbItem key={path}> |
||||
<NextLink href={`/${pathSplit.slice(0, idx + 1).join('/')}`} passHref> |
||||
<BreadcrumbLink color={idx + 1 === pathSplit.length ? 'body' : 'primary'}> |
||||
{path} |
||||
</BreadcrumbLink> |
||||
</NextLink> |
||||
</BreadcrumbItem> |
||||
); |
||||
})} |
||||
</Breadcrumb> |
||||
) : ( |
||||
<Stack h='24px'></Stack> |
||||
)} |
||||
</> |
||||
); |
||||
}; |
@ -0,0 +1,81 @@ |
||||
import { FC } from 'react'; |
||||
import { |
||||
Accordion, |
||||
AccordionButton, |
||||
AccordionItem, |
||||
AccordionPanel, |
||||
Center, |
||||
Link, |
||||
Stack, |
||||
Text |
||||
} from '@chakra-ui/react'; |
||||
import { AddIcon, MinusIcon } from '@chakra-ui/icons'; |
||||
import NextLink from 'next/link'; |
||||
|
||||
import { LinksList } from './'; |
||||
|
||||
import { NavLink } from '../../../types'; |
||||
|
||||
interface Props { |
||||
navLinks: NavLink[]; |
||||
} |
||||
|
||||
export const DocsLinks: FC<Props> = ({ navLinks }) => ( |
||||
<Stack border='2px' borderColor='primary'> |
||||
{navLinks.map(({ id, to, items }, idx) => { |
||||
return ( |
||||
<Accordion key={id} allowToggle mt='0 !important' defaultIndex={[0]}> |
||||
<AccordionItem border='none'> |
||||
{({ isExpanded }) => ( |
||||
<> |
||||
<AccordionButton |
||||
borderBottom={navLinks.length - 1 === idx ? 'none' : '2px'} |
||||
p={0} |
||||
borderColor='primary' |
||||
justifyContent='space-between' |
||||
placeContent='flex-end' |
||||
bg='button-bg' |
||||
> |
||||
<Stack |
||||
p={4} |
||||
borderRight={items ? '2px' : 'none'} |
||||
borderColor='primary' |
||||
w='100%' |
||||
bg='bg' |
||||
> |
||||
{to ? ( |
||||
<NextLink href={to} passHref> |
||||
<Link> |
||||
<Text textStyle='docs-nav-dropdown'>{id}</Text> |
||||
</Link> |
||||
</NextLink> |
||||
) : ( |
||||
<Text textStyle='docs-nav-dropdown'>{id}</Text> |
||||
)} |
||||
</Stack> |
||||
|
||||
{items && ( |
||||
<Stack minW='61px'> |
||||
<Center> |
||||
{isExpanded ? ( |
||||
<MinusIcon w='20px' h='20px' color='primary' /> |
||||
) : ( |
||||
<AddIcon w='20px' h='20px' color='primary' /> |
||||
)} |
||||
</Center> |
||||
</Stack> |
||||
)} |
||||
</AccordionButton> |
||||
{items && ( |
||||
<AccordionPanel borderBottom='2px solid' borderColor='primary' px={0} py={4}> |
||||
<LinksList links={items} /> |
||||
</AccordionPanel> |
||||
)} |
||||
</> |
||||
)} |
||||
</AccordionItem> |
||||
</Accordion> |
||||
); |
||||
})} |
||||
</Stack> |
||||
); |
@ -0,0 +1,59 @@ |
||||
import { FC } from 'react'; |
||||
import { |
||||
Accordion, |
||||
AccordionButton, |
||||
AccordionIcon, |
||||
AccordionItem, |
||||
AccordionPanel, |
||||
Stack, |
||||
Text |
||||
} from '@chakra-ui/react'; |
||||
import { DocsLinks } from './DocsLinks'; |
||||
|
||||
import { NavLink } from '../../../types'; |
||||
|
||||
interface Props { |
||||
navLinks: NavLink[]; |
||||
} |
||||
|
||||
export const DocsNav: FC<Props> = ({ navLinks }) => { |
||||
return ( |
||||
<Stack w={{ base: '100%', lg: 72 }}> |
||||
<Stack display={{ base: 'none', lg: 'block' }}> |
||||
<DocsLinks navLinks={navLinks} /> |
||||
</Stack> |
||||
|
||||
<Stack display={{ base: 'block', lg: 'none' }}> |
||||
<Accordion allowToggle> |
||||
<AccordionItem border='none'> |
||||
<AccordionButton |
||||
display='flex' |
||||
py={4} |
||||
px={8} |
||||
border='2px' |
||||
borderColor='primary' |
||||
placeContent='space-between' |
||||
bg='button-bg' |
||||
_hover={{ |
||||
bg: 'primary', |
||||
color: 'bg' |
||||
}} |
||||
_expanded={{ |
||||
bg: 'primary', |
||||
color: 'bg' |
||||
}} |
||||
> |
||||
<Text as='h4' textStyle='docs-nav-dropdown'> |
||||
Documentation |
||||
</Text> |
||||
<AccordionIcon /> |
||||
</AccordionButton> |
||||
<AccordionPanel p={0}> |
||||
<DocsLinks navLinks={navLinks} /> |
||||
</AccordionPanel> |
||||
</AccordionItem> |
||||
</Accordion> |
||||
</Stack> |
||||
</Stack> |
||||
); |
||||
}; |
@ -0,0 +1,44 @@ |
||||
import { FC } from 'react'; |
||||
import { Divider, Link, Stack, Text } from '@chakra-ui/react'; |
||||
import NextLink from 'next/link'; |
||||
|
||||
import { parseHeadingId } from '../../../utils/parseHeadingId'; |
||||
import { useActiveHash } from '../../../hooks/useActiveHash'; |
||||
|
||||
interface Props { |
||||
content: string; |
||||
} |
||||
|
||||
export const DocumentNav: FC<Props> = ({ content }) => { |
||||
const parsedHeadings = content |
||||
.split('\n\n') |
||||
.map(item => item.replace(/[\n\r]/g, '')) |
||||
.filter(item => item.startsWith('#')) |
||||
.map(item => parseHeadingId([item])) |
||||
.filter(item => item); |
||||
|
||||
const activeHash = useActiveHash(parsedHeadings.map(heading => heading!.headingId)); |
||||
|
||||
return ( |
||||
<Stack position='sticky' top='4'> |
||||
<Text as='h5' textStyle='document-nav-title'> |
||||
on this page |
||||
</Text> |
||||
<Divider borderColor='primary' my={`4 !important`} /> |
||||
{parsedHeadings.map((heading, idx) => { |
||||
return ( |
||||
<NextLink key={`${idx} ${heading?.title}`} href={`#${heading?.headingId}`}> |
||||
<Link m={0}> |
||||
<Text |
||||
color={activeHash === heading?.headingId ? 'body' : 'primary'} |
||||
textStyle='document-nav-link' |
||||
> |
||||
{heading?.title} |
||||
</Text> |
||||
</Link> |
||||
</NextLink> |
||||
); |
||||
})} |
||||
</Stack> |
||||
); |
||||
}; |
@ -0,0 +1,35 @@ |
||||
import { FC } from 'react'; |
||||
import { Link, Stack, Text } from '@chakra-ui/react'; |
||||
import NextLink from 'next/link'; |
||||
|
||||
import { NavLink } from '../../../types'; |
||||
|
||||
interface LinksListProps { |
||||
links: NavLink[]; |
||||
} |
||||
|
||||
export const LinksList: FC<LinksListProps> = ({ links }) => ( |
||||
<Stack px={4}> |
||||
{links.map(({ id, to, items }) => { |
||||
return to ? ( |
||||
<Stack key={id}> |
||||
<NextLink href={to} passHref key={id}> |
||||
<Link> |
||||
<Text textStyle='docs-nav-links' color={items ? 'primary' : 'body'}> |
||||
{id} |
||||
</Text> |
||||
</Link> |
||||
</NextLink> |
||||
{items && <LinksList links={items} />} |
||||
</Stack> |
||||
) : ( |
||||
<Stack key={id}> |
||||
<Text textStyle='docs-nav-links' color={items ? 'primary' : 'body'}> |
||||
{id} |
||||
</Text> |
||||
{items && <LinksList links={items} />} |
||||
</Stack> |
||||
); |
||||
})} |
||||
</Stack> |
||||
); |
@ -0,0 +1,153 @@ |
||||
import { |
||||
Flex, |
||||
Heading, |
||||
Link, |
||||
ListItem, |
||||
OrderedList, |
||||
Stack, |
||||
Table, |
||||
Text, |
||||
UnorderedList |
||||
} from '@chakra-ui/react'; |
||||
import NextLink from 'next/link'; |
||||
|
||||
import { Code, Note } from '.'; |
||||
import { textStyles } from '../../../theme/foundations'; |
||||
import { parseHeadingId } from '../../../utils/parseHeadingId'; |
||||
|
||||
const { header1, header2, header3, header4 } = textStyles; |
||||
|
||||
const MDComponents = { |
||||
// paragraphs
|
||||
p: ({ children }: any) => { |
||||
return ( |
||||
<Text mb='7 !important' lineHeight={1.5}> |
||||
{children} |
||||
</Text> |
||||
); |
||||
}, |
||||
// links
|
||||
a: ({ children, href }: any) => { |
||||
return ( |
||||
<NextLink href={href} passHref> |
||||
<Link |
||||
isExternal={href.startsWith('http') && !href.includes('geth.ethereum.org')} |
||||
variant='light' |
||||
> |
||||
{children} |
||||
</Link> |
||||
</NextLink> |
||||
); |
||||
}, |
||||
// headings
|
||||
h1: ({ children }: any) => { |
||||
const heading = parseHeadingId(children); |
||||
|
||||
return heading ? ( |
||||
<Heading as='h1' textAlign='start' mb='5 !important' {...header1} id={heading.headingId}> |
||||
{heading.children} |
||||
</Heading> |
||||
) : ( |
||||
<Heading as='h1' textAlign='start' mb='5 !important' {...header1}> |
||||
{children} |
||||
</Heading> |
||||
); |
||||
}, |
||||
h2: ({ children }: any) => { |
||||
const heading = parseHeadingId(children); |
||||
|
||||
return heading ? ( |
||||
<Heading |
||||
as='h2' |
||||
textAlign='start' |
||||
mt='16 !important' |
||||
mb='4 !important' |
||||
{...header2} |
||||
id={heading.headingId} |
||||
> |
||||
{heading.children} |
||||
</Heading> |
||||
) : ( |
||||
<Heading as='h2' textAlign='start' mt='16 !important' mb='4 !important' {...header2}> |
||||
{children} |
||||
</Heading> |
||||
); |
||||
}, |
||||
h3: ({ children }: any) => { |
||||
const heading = parseHeadingId(children); |
||||
|
||||
return heading ? ( |
||||
<Heading as='h3' mt='5 !important' mb='2.5 !important' {...header3} id={heading.headingId}> |
||||
{heading.children} |
||||
</Heading> |
||||
) : ( |
||||
<Heading as='h3' mt='5 !important' mb='2.5 !important' {...header3}> |
||||
{children} |
||||
</Heading> |
||||
); |
||||
}, |
||||
h4: ({ children }: any) => { |
||||
const heading = parseHeadingId(children); |
||||
|
||||
return heading ? ( |
||||
<Heading as='h4' mb='2.5 !important' {...header4} id={heading.headingId}> |
||||
{heading.children} |
||||
</Heading> |
||||
) : ( |
||||
<Heading as='h4' mb='2.5 !important' {...header4}> |
||||
{children} |
||||
</Heading> |
||||
); |
||||
}, |
||||
// tables
|
||||
table: ({ children }: any) => ( |
||||
<Flex maxW='min(100%, 100vw)' overflowX='auto'> |
||||
<Table |
||||
variant='striped' |
||||
colorScheme='greenAlpha' |
||||
border='1px' |
||||
borderColor='blackAlpha.50' |
||||
my='6 !important' |
||||
size={{ base: 'sm', lg: 'md' }} |
||||
w='auto' |
||||
> |
||||
{children} |
||||
</Table> |
||||
</Flex> |
||||
), |
||||
// pre
|
||||
pre: ({ children }: any) => ( |
||||
<Stack mb={5}> |
||||
<pre>{children}</pre> |
||||
</Stack> |
||||
), |
||||
// code
|
||||
code: ({ children, ...props }: any) => <Code {...props}>{children}</Code>, |
||||
// list
|
||||
ul: ({ children }: any) => { |
||||
return ( |
||||
<Stack> |
||||
<UnorderedList mb={7} px={4}> |
||||
{children} |
||||
</UnorderedList> |
||||
</Stack> |
||||
); |
||||
}, |
||||
ol: ({ children }: any) => { |
||||
return ( |
||||
<Stack> |
||||
<OrderedList mb={7} px={4}> |
||||
{children} |
||||
</OrderedList> |
||||
</Stack> |
||||
); |
||||
}, |
||||
li: ({ children }: any) => { |
||||
return <ListItem color='primary'>{children}</ListItem>; |
||||
}, |
||||
note: ({ children }: any) => { |
||||
return <Note>{children}</Note>; |
||||
} |
||||
}; |
||||
|
||||
export default MDComponents; |
@ -0,0 +1,17 @@ |
||||
import { FC } from 'react'; |
||||
import { Stack, Text } from '@chakra-ui/react'; |
||||
|
||||
interface Props { |
||||
children: string[]; |
||||
} |
||||
|
||||
export const Note: FC<Props> = ({ children }) => { |
||||
return ( |
||||
<Stack w='100%' bg='button-bg' border='2px' borderColor='primary' p={4}> |
||||
<Text as='h4' textStyle='header4'> |
||||
Note |
||||
</Text> |
||||
<Text textStyle='note-text'>{children}</Text> |
||||
</Stack> |
||||
); |
||||
}; |
@ -0,0 +1,8 @@ |
||||
export * from './Breadcrumbs'; |
||||
export * from './Code'; |
||||
export * from './DocsLinks'; |
||||
export * from './DocsNav'; |
||||
export * from './DocumentNav'; |
||||
export * from './LinkList'; |
||||
export * from './Note'; |
||||
export { default } from './MDComponents'; |
@ -1 +0,0 @@ |
||||
export * from './Code'; |
@ -1,27 +0,0 @@ |
||||
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink } from '@chakra-ui/react'; |
||||
import NextLink from 'next/link'; |
||||
import { useRouter } from 'next/router'; |
||||
import { FC } from 'react'; |
||||
|
||||
export const Breadcrumbs: FC = () => { |
||||
const router = useRouter(); |
||||
|
||||
let pathSplit = router.asPath.split('/'); |
||||
pathSplit = pathSplit.splice(1, pathSplit.length); |
||||
|
||||
return ( |
||||
<Breadcrumb> |
||||
{pathSplit.map((path: string, idx: number) => { |
||||
return ( |
||||
<BreadcrumbItem key={path}> |
||||
<NextLink href={`/${pathSplit.slice(0, idx + 1).join('/')}`} passHref> |
||||
<BreadcrumbLink color={idx + 1 === pathSplit.length ? 'body' : 'primary'}> |
||||
{path} |
||||
</BreadcrumbLink> |
||||
</NextLink> |
||||
</BreadcrumbItem> |
||||
); |
||||
})} |
||||
</Breadcrumb> |
||||
); |
||||
}; |
@ -1 +0,0 @@ |
||||
export * from './Breadcrumbs'; |
@ -1 +0,0 @@ |
||||
export { default } from './MDXComponents'; |
@ -0,0 +1,149 @@ |
||||
- id: Getting started |
||||
to: /docs/getting-started |
||||
items: |
||||
- id: Hardware requirements |
||||
to: /docs/getting-started/hardware-requirements |
||||
- id: Installing Geth |
||||
to: /docs/getting-started/installing-geth |
||||
- id: Consensus clients |
||||
to: /docs/getting-started/consensus-clients |
||||
- id: Fundamentals |
||||
to: /docs/fundamentals |
||||
items: |
||||
- id: Node architecture |
||||
to: /docs/fundamentals/node-architecture |
||||
- id: Command-line options |
||||
to: /docs/fundamentals/command-line-options |
||||
- id: Security |
||||
to: /docs/fundamentals/security |
||||
- id: Sync-modes |
||||
to: /docs/fundamentals/sync-modes |
||||
- id: Account management |
||||
to: /docs/fundamentals/account-management |
||||
- id: Backup restore |
||||
to: /docs/fundamentals/backup-restore |
||||
- id: Logs |
||||
to: /docs/fundamentals/logs |
||||
- id: Peer-to-peer |
||||
to: /docs/fundamentals/peer-to-peer |
||||
- id: Pruning |
||||
to: /docs/fundamentals/pruning |
||||
- id: Light client |
||||
to: /docs/fundamentals/les |
||||
- id: Mining |
||||
to: /docs/fundamentals/mining |
||||
- id: Interacting with Geth |
||||
items: |
||||
- id: JSON-RPC Server |
||||
to: /docs/interacting-with-geth/rpc |
||||
items: |
||||
- id: Batch requests |
||||
to: /docs/interacting-with-geth/rpc/batch |
||||
- id: GraphQL server |
||||
to: /docs/interacting-with-geth/rpc/graphql |
||||
- id: admin Namespace |
||||
to: /docs/interacting-with-geth/rpc/ns-admin |
||||
- id: clique Namespace |
||||
to: /docs/interacting-with-geth/rpc/ns-clique |
||||
- id: debug Namespace |
||||
to: /docs/interacting-with-geth/rpc/ns-debug |
||||
- id: eth Namespace |
||||
to: /docs/interacting-with-geth/rpc/ns-eth |
||||
- id: les Namespace |
||||
to: /docs/interacting-with-geth/rpc/ns-les |
||||
- id: miner Namespace |
||||
to: /docs/interacting-with-geth/rpc/ns-miner |
||||
- id: net Namespace |
||||
to: /docs/interacting-with-geth/rpc/ns-net |
||||
- id: Personal namespace deprecation notes |
||||
to: /docs/interacting-with-geth/rpc/ns-personal-deprecation |
||||
- id: Personal Namespace |
||||
to: /docs/interacting-with-geth/rpc/ns-personal |
||||
- id: txpool Namespace |
||||
to: /docs/interacting-with-geth/rpc/ns-txpool |
||||
- id: Objects |
||||
to: /docs/interacting-with-geth/rpc/objects |
||||
- id: Real-time Events |
||||
to: /docs/interacting-with-geth/rpc/pubsub |
||||
- id: JavaScript Console |
||||
to: /docs/interacting-with-geth/javascript-console |
||||
- id: 'JavaScript Console 2: Contracts' |
||||
to: /docs/interacting-with-geth/javascript-console-contracts |
||||
- id: Developers |
||||
to: /docs/developers |
||||
items: |
||||
- id: Dapp developers |
||||
items: |
||||
- id: Go API |
||||
to: /docs/developers/dapp-developer/native |
||||
- id: Go Account Management |
||||
to: /docs/developers/dapp-developer/native-accounts |
||||
- id: Go Contract Bindings |
||||
to: /docs/developers/dapp-developer/native-bindings |
||||
- id: Geth for Mobile |
||||
to: /docs/developers/dapp-developer/mobile |
||||
- id: EVM tracing |
||||
to: /docs/developers/evm-tracing |
||||
items: |
||||
- id: Basic traces |
||||
to: /docs/developers/evm-tracing/basic-traces |
||||
- id: Built-in tracers |
||||
to: /docs/developers/evm-tracing/built-in-tracers |
||||
- id: Custom EVM tracer |
||||
to: /docs/developers/evm-tracing/custom-tracer |
||||
- id: Tutorial for Javascript tracing |
||||
to: /docs/developers/evm-tracing/javascript-tutorial |
||||
- id: Geth developer |
||||
items: |
||||
- id: Developer guide |
||||
to: /docs/developers/geth-developer/dev-guide |
||||
- id: Developer mode |
||||
to: /docs/developers/geth-developer/dev-mode |
||||
- id: Disclosures |
||||
to: /docs/developers/geth-developer/disclosures |
||||
- id: Issue handling workflow |
||||
to: /docs/developers/geth-developer/issue-handling-workflow |
||||
- id: DNS discovery setup guide |
||||
to: /docs/developers/geth-developer/dns-discovery-setup |
||||
- id: Code review guidelines |
||||
to: /docs/developers/geth-developer/code-review-guidelines |
||||
- id: Private networks |
||||
to: /docs/developers/geth-developer/private-network |
||||
- id: Contributing |
||||
to: /docs/developers/contributing |
||||
- id: Monitoring |
||||
items: |
||||
- id: Dashboards |
||||
to: /docs/monitoring/dashboards |
||||
- id: Ethstats |
||||
to: /docs/monitoring/ethstats |
||||
- id: Metrics |
||||
to: /docs/monitoring/metrics |
||||
- id: Tools |
||||
items: |
||||
- id: Clef |
||||
items: |
||||
- id: Introduction |
||||
to: /docs/tools/clef/introduction |
||||
- id: APIs |
||||
to: /docs/tools/clef/apis |
||||
- id: Rules |
||||
to: /docs/tools/clef/rules |
||||
- id: Setup |
||||
to: /docs/tools/clef/setup |
||||
- id: Datatypes |
||||
to: /docs/tools/clef/datatypes |
||||
- id: Tutorial |
||||
to: /docs/tools/clef/tutorial |
||||
- id: Clique-signing |
||||
to: /docs/tools/clef/clique-signing |
||||
- id: puppeth |
||||
to: /docs/tools/puppeth |
||||
- id: Abigen |
||||
to: /docs/tools/abigen |
||||
- id: devp2p |
||||
to: /docs/tools/devp2p |
||||
- id: FAQs |
||||
to: /docs/faq |
||||
- id: Resources |
||||
to: /docs/resources |
@ -0,0 +1,42 @@ |
||||
import { useState, useEffect } from 'react'; |
||||
|
||||
/** |
||||
* A hook to determine which section of the page is currently in the viewport. |
||||
* @param {*} itemIds Array of document ids to observe |
||||
* @param {*} rootMargin |
||||
* @returns id of the element currently in viewport |
||||
*/ |
||||
export const useActiveHash = (itemIds: Array<string>, rootMargin = `0% 0% -80% 0%`): string => { |
||||
const [activeHash, setActiveHash] = useState(``); |
||||
|
||||
useEffect(() => { |
||||
const observer = new IntersectionObserver( |
||||
entries => { |
||||
entries.forEach(entry => { |
||||
if (entry.isIntersecting) { |
||||
setActiveHash(`${entry.target.id}`); |
||||
} |
||||
}); |
||||
}, |
||||
{ rootMargin } |
||||
); |
||||
|
||||
itemIds?.forEach(id => { |
||||
const element = document.getElementById(id); |
||||
if (element !== null) { |
||||
observer.observe(element); |
||||
} |
||||
}); |
||||
|
||||
return () => { |
||||
itemIds?.forEach(id => { |
||||
const element = document.getElementById(id); |
||||
if (element !== null) { |
||||
observer.unobserve(element); |
||||
} |
||||
}); |
||||
}; |
||||
}, [itemIds, rootMargin]); |
||||
|
||||
return activeHash; |
||||
}; |
@ -0,0 +1,16 @@ |
||||
import fs from 'fs'; |
||||
|
||||
export const getFileList = (dirName: string) => { |
||||
let files: string[] = []; |
||||
const items = fs.readdirSync(dirName, { withFileTypes: true }); |
||||
|
||||
for (const item of items) { |
||||
if (item.isDirectory()) { |
||||
files = [...files, ...getFileList(`${dirName}/${item.name}`)]; |
||||
} else { |
||||
files.push(`/${dirName}/${item.name}`); |
||||
} |
||||
} |
||||
|
||||
return files.map(file => file.replace('.md', '')).map(file => file.replace('/index', '')); |
||||
}; |
@ -0,0 +1,18 @@ |
||||
const check = '{#'; |
||||
|
||||
export const parseHeadingId = (children: string[]) => { |
||||
if (children[children.length - 1].includes(check)) { |
||||
const temp = children[children.length - 1].split(check); |
||||
const headingId = temp[temp.length - 1].split('}')[0]; |
||||
|
||||
children[children.length - 1] = temp[0]; |
||||
|
||||
return { |
||||
children, |
||||
title: temp[0].replaceAll('#', ''), |
||||
headingId |
||||
}; |
||||
} |
||||
|
||||
return null; |
||||
}; |
Loading…
Reference in new issue