| import { productMap } from '@/products/lib/all-products' | |
| interface TocItem { | |
| type: 'category' | 'subcategory' | 'article' | |
| href: string | |
| } | |
| interface Page { | |
| relativePath: string | |
| markdown: string | |
| } | |
| const productTOCs = Object.values(productMap) | |
| .filter((product) => !product.external) | |
| .map((product) => product.toc.replace('content/', '')) | |
| const linkString = /{% [^}]*?link.*? \/(.*?) ?%}/m | |
| const linksArray = new RegExp(linkString.source, 'gm') | |
| // return an array of objects like { type: 'category|subcategory|article', href: 'path' } | |
| export default function getTocItems(page: Page): TocItem[] | undefined { | |
| // only process product and category tocs | |
| if (!page.relativePath.endsWith('index.md')) return | |
| if (page.relativePath === 'index.md') return | |
| // ignore content above Table of Contents heading | |
| const pageContent = page.markdown.replace(/[\s\S]*?# Table of contents\n/im, '') | |
| // find array of TOC link strings | |
| const rawItems = pageContent.match(linksArray) | |
| // return an empty array if this is a localized page | |
| if (!rawItems) { | |
| return [] | |
| } | |
| return rawItems | |
| .map((item: string) => { | |
| const match = item.match(linkString) | |
| if (!match) return null | |
| const tocItem: TocItem = {} as TocItem | |
| // a product's toc items are always categories | |
| // whereas a category's toc items can be either subcategories or articles | |
| tocItem.type = productTOCs.includes(page.relativePath) | |
| ? 'category' | |
| : page.relativePath.includes('/index.md') | |
| ? 'subcategory' | |
| : 'article' | |
| tocItem.href = match[1] | |
| return tocItem | |
| }) | |
| .filter((item): item is TocItem => item !== null) | |
| } | |