| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- import { slugifyWithCounter } from '@sindresorhus/slugify'
- import { useRouter } from 'next/router'
- import { products } from '@/components/products'
- export function usePage(pageProps) {
- const { pathname } = useRouter()
- const title = pageProps.markdoc?.frontmatter.title ?? 'Metaplex Documentation'
- const product = getActiveProduct(pathname, pageProps)
- const activeSection = getActiveSection(pathname, product, pageProps)
- const activeHero = getActiveHero(pathname, product, pageProps)
- return {
- title,
- metaTitle: pageProps.markdoc?.frontmatter.metaTitle ?? title,
- pathname,
- product,
- activeHero,
- activeSection,
- isIndexPage: product?.path ? pathname === `/${product.path}` : false,
- tableOfContents: pageProps.markdoc?.content
- ? parseTableOfContents(pageProps.markdoc.content)
- : [],
- }
- }
- function getActiveProduct(pathname, pageProps) {
- const pathnameFirstSegment = pathname.replace(/^\/|\/$/, '').split('/')?.[0]
- const foundProduct = products.find((product) => {
- const defaultIsPageFromProduct = () => {
- if (product.isFallbackProduct) return false
- return product.path === pathnameFirstSegment
- }
- return product.isPageFromProduct
- ? product.isPageFromProduct({ pathname, product, pageProps })
- : defaultIsPageFromProduct()
- })
- if (foundProduct) return foundProduct
- const fallbackProduct = products.find((product) => product.isFallbackProduct)
- if (fallbackProduct) return fallbackProduct
- throw new Error('No product found')
- }
- function getActiveHero(pathname, product, pageProps) {
- if (!product?.heroes) return undefined
- return (
- product.heroes.find((hero) => {
- return hero.doesPageHaveHero
- ? hero.doesPageHaveHero({ pathname, hero, product, pageProps })
- : pathname === hero.path
- })?.component ?? undefined
- )
- }
- function getActiveSection(pathname, product, pageProps) {
- if (!product?.sections) return undefined
- // Find active section.
- const foundSection = product.sections.find((section) => {
- const defaultIsPageFromSection = () => {
- if (section.isFallbackSection) return false
- return (
- pathname.startsWith(`${section.href}/`) || pathname === section.href
- )
- }
- return section.isPageFromSection
- ? section.isPageFromSection({ pathname, section, product, pageProps })
- : defaultIsPageFromSection()
- })
- const fallbackSection = product.sections.find(
- (section) => section.isFallbackSection
- )
- const activeSection =
- foundSection || fallbackSection
- ? { ...(foundSection ?? fallbackSection) }
- : undefined
- // Add navigation helpers.
- if (activeSection && activeSection.navigation) {
- const allLinks = activeSection.navigation.flatMap((group) => group.links)
- const linkIndex = allLinks.findIndex((link) => link.href === pathname)
- activeSection.previousPage = allLinks[linkIndex - 1]
- activeSection.nextPage = allLinks[linkIndex + 1]
- activeSection.navigationGroup = activeSection.navigation.find((group) =>
- group.links.find((link) => link.href === pathname)
- )
- }
- return activeSection
- }
- function parseTableOfContents(nodes, slugify = slugifyWithCounter()) {
- let sections = []
- for (let node of nodes) {
- if (node.name === 'h2' || node.name === 'h3') {
- let title = getNodeText(node)
- if (title) {
- let id = slugify(title)
- node.attributes.id = id
- if (node.name === 'h3') {
- if (!sections[sections.length - 1]) {
- throw new Error(
- 'Cannot add `h3` to table of contents without a preceding `h2`'
- )
- }
- sections[sections.length - 1].children.push({
- ...node.attributes,
- title,
- })
- } else {
- sections.push({ ...node.attributes, title, children: [] })
- }
- }
- }
- sections.push(...parseTableOfContents(node.children ?? [], slugify))
- }
- return sections
- }
- function getNodeText(node) {
- let text = ''
- for (let child of node.children ?? []) {
- if (typeof child === 'string') {
- text += child
- }
- text += getNodeText(child)
- }
- return text
- }
|