29044867dd
This PR adds the docs app back into the tldraw monorepo. ## Deploying We'll want to update our deploy script to update the SOURCE_SHA to the newest release sha... and then deploy the docs pulling api.json files from that release. We _could_ update the docs on every push to main, but we don't have to unless something has changed. Right now there's no automated deployments from this repo. ## Side effects To make this one work, I needed to update the lock file. This might be ok (new year new lock file), and everything builds as expected, though we may want to spend some time with our scripts to be sure that things are all good. I also updated our prettier installation, which decided to add trailing commas to every generic type. Which is, I suppose, [correct behavior](https://github.com/prettier/prettier-vscode/issues/955)? But that caused diffs in every file, which is unfortunate. ### Change Type - [x] `internal` — Any other changes that don't affect the published package[^2]
119 lines
3.2 KiB
TypeScript
119 lines
3.2 KiB
TypeScript
import { ArticleDocsPage } from '@/components/ArticleDocsPage'
|
|
import { CategoryDocsPage } from '@/components/CategoryDocsPage'
|
|
import { SectionDocsPage } from '@/components/SectionDocsPage'
|
|
import { getDb } from '@/utils/ContentDatabase'
|
|
import { Metadata } from 'next'
|
|
import { notFound } from 'next/navigation'
|
|
|
|
async function getContentForPath(path: string) {
|
|
const db = await getDb()
|
|
|
|
const section = await db.db.get(`SELECT * FROM sections WHERE sections.path = ?`, path)
|
|
if (section) return { type: 'section', section } as const
|
|
|
|
const category = await db.db.get(`SELECT * FROM categories WHERE categories.path = ?`, path)
|
|
if (category) return { type: 'category', category } as const
|
|
|
|
const article = await db.db.get(`SELECT * FROM articles WHERE articles.path = ?`, path)
|
|
if (article) return { type: 'article', article } as const
|
|
|
|
throw Error(`No content found for ${path}`)
|
|
}
|
|
|
|
export async function generateMetadata({ params }: { params: { id: string | string[] } }) {
|
|
const path = typeof params.id === 'string' ? [params.id] : params.id
|
|
const pathString = '/' + path.join('/')
|
|
const content = await getContentForPath(pathString)
|
|
|
|
if (!content) return {}
|
|
|
|
let title: string | undefined
|
|
let description: string | undefined
|
|
let hero: string | undefined
|
|
|
|
switch (content.type) {
|
|
case 'section': {
|
|
const { section } = content
|
|
title = section.title
|
|
description = section.description ?? undefined
|
|
hero = section.hero ?? undefined
|
|
break
|
|
}
|
|
case 'category': {
|
|
const { category } = content
|
|
title = category.title
|
|
description = category.description ?? undefined
|
|
hero = category.hero ?? undefined
|
|
break
|
|
}
|
|
case 'article': {
|
|
const { article } = content
|
|
title = article.title
|
|
description = article.description ?? undefined
|
|
hero = article.hero ?? undefined
|
|
break
|
|
}
|
|
}
|
|
|
|
const metadata: Metadata = {
|
|
title,
|
|
description: description,
|
|
openGraph: {
|
|
title: title,
|
|
description: description,
|
|
images: hero,
|
|
},
|
|
twitter: {
|
|
description: description,
|
|
images: hero,
|
|
},
|
|
}
|
|
|
|
return metadata
|
|
}
|
|
|
|
export async function generateStaticParams() {
|
|
const db = await getDb()
|
|
|
|
const sections = await db.db.all(`SELECT * FROM sections`)
|
|
const categories = await db.db.all(`SELECT * FROM categories`)
|
|
const articles = await db.db.all(`SELECT * FROM articles`)
|
|
|
|
const paths = [] as string[]
|
|
|
|
for (const section of sections) {
|
|
paths.push(section.path)
|
|
}
|
|
|
|
for (const category of categories) {
|
|
paths.push(category.path)
|
|
}
|
|
|
|
for (const article of articles) {
|
|
paths.push(article.path)
|
|
}
|
|
|
|
return paths.map((path) => ({ params: { id: path.split('/').filter((p) => p) } }))
|
|
}
|
|
|
|
export default async function ContentPage({ params }: { params: { id: string | string[] } }) {
|
|
const path = typeof params.id === 'string' ? [params.id] : params.id
|
|
const pathString = '/' + path.join('/')
|
|
const content = await getContentForPath(pathString)
|
|
if (!content) throw notFound()
|
|
|
|
switch (content.type) {
|
|
case 'section': {
|
|
return <SectionDocsPage section={content.section} />
|
|
}
|
|
case 'category': {
|
|
return <CategoryDocsPage category={content.category} />
|
|
}
|
|
case 'article': {
|
|
return <ArticleDocsPage article={content.article} />
|
|
}
|
|
default: {
|
|
throw notFound()
|
|
}
|
|
}
|
|
}
|