mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
## Summary - `contentlayer2@0.4.6` is unmaintained and drags in a heavy, stale dependency graph (esbuild pinned to 0.17–0.20, mdx-bundler, old `@opentelemetry/core`) that was the recurring source of vuln bumps. - Migrates all three apps that used it — `design-system`, `ui-library`, `learn` — to [Velite](https://velite.js.org), preserving the generated typed `allDocs`/`Doc` collection and the `body.code` + `useMDXComponent` runtime via a small shared local hook. - Same MDX pipeline (remark-gfm, remark-code-import, rehype-slug, rehype-pretty-code w/ Shiki compat + local theme, rehype-autolink-headings, custom `__rawString__`/`__src__`/`__event__`/`__style__` visitors) ported 1:1 into each app's `velite.config.js`. - `learn`'s extra frontmatter fields (`chapterNumber`, `explore`, `courseHero`) are now backed by real Velite/Zod schema types, so the `(doc as any)` casts in `get-next-page.ts` / `get-current-chapter.ts` / the doc page could be dropped. - `next.config.mjs` no longer wraps with `withContentlayer`; since Velite has no Next.js webpack-plugin equivalent, each app's `dev` script now runs `velite dev` and `next dev` in parallel via `npm-run-all`. Ref: [FE-3861](https://linear.app/supabase/issue/FE-3861/migrate-off-contentlayer2-learn-ui-library-design-system-to-shed) ## Test plan - [x] `pnpm build:content` (Velite build) succeeds for all three apps - [x] `pnpm typecheck` passes for all three apps - [ ] Manual smoke test of `pnpm dev` for each app in a browser (docs pages render, TOC, copy-button, code highlighting) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Improvements** * Improved content generation across documentation, learning materials, and the UI library for more consistent pages. * Preserved MDX rendering, navigation, table of contents, course metadata, source previews, and component examples. * Improved consistency when displaying documentation and interactive examples. * Improved application loading by optimizing how interface components are delivered. * **Chores** * Streamlined content compilation and development workflows across the design system, learning area, and UI library. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
198 lines
6.5 KiB
TypeScript
198 lines
6.5 KiB
TypeScript
import Link from 'next/link'
|
|
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, cn } from 'ui'
|
|
|
|
import { BlockItem } from './block-item'
|
|
import { BlockPreview } from './block-preview'
|
|
import { Callout } from './callout'
|
|
import { ComponentPreview } from './component-preview'
|
|
import { CopyButton } from './copy-button'
|
|
import { DualRealtimeChat } from './dual-realtime-chat'
|
|
import { DualRealtimeFlow } from './dual-realtime-flow'
|
|
import { DualRealtimeMonaco } from './dual-realtime-monaco'
|
|
import { RegistryBlock } from './registry-block'
|
|
import { StyleWrapper } from './style-wrapper'
|
|
import TanStackBeta from './tanstack-beta'
|
|
import { TanstackDBGenerator } from './tanstack-db-generator'
|
|
import { useMDXComponent } from '@/lib/use-mdx-component'
|
|
import type { Style } from '@/registry/styles'
|
|
|
|
const components = {
|
|
RegistryBlock,
|
|
Accordion,
|
|
AccordionContent,
|
|
AccordionItem,
|
|
AccordionTrigger,
|
|
h1: ({ className, ...props }: React.HTMLAttributes<HTMLHeadingElement>) => (
|
|
<h1 className={cn('font-heading mt-2 scroll-m-20 text-4xl font-bold', className)} {...props} />
|
|
),
|
|
h2: ({ className, ...props }: React.HTMLAttributes<HTMLHeadingElement>) => (
|
|
<h2
|
|
className={cn(
|
|
'font-heading mt-12 scroll-m-20 border-b pb-2 text-2xl tracking-tight first:mt-0',
|
|
className
|
|
)}
|
|
{...props}
|
|
/>
|
|
),
|
|
h3: ({ className, ...props }: React.HTMLAttributes<HTMLHeadingElement>) => (
|
|
<h3
|
|
className={cn('font-heading mt-8 scroll-m-20 text-xl tracking-tight', className)}
|
|
{...props}
|
|
/>
|
|
),
|
|
h4: ({ className, ...props }: React.HTMLAttributes<HTMLHeadingElement>) => (
|
|
<h4
|
|
className={cn('font-heading mt-8 scroll-m-20 text-lg tracking-tight', className)}
|
|
{...props}
|
|
/>
|
|
),
|
|
h5: ({ className, ...props }: React.HTMLAttributes<HTMLHeadingElement>) => (
|
|
<h5 className={cn('mt-8 scroll-m-20 text-lg tracking-tight', className)} {...props} />
|
|
),
|
|
h6: ({ className, ...props }: React.HTMLAttributes<HTMLHeadingElement>) => (
|
|
<h6 className={cn('mt-8 scroll-m-20 text-base tracking-tight', className)} {...props} />
|
|
),
|
|
a: ({ className, ...props }: React.HTMLAttributes<HTMLAnchorElement>) => (
|
|
<a
|
|
className={cn(
|
|
'text-foreground underline decoration-1 decoration-foreground-muted underline-offset-4 transition-colors hover:decoration-brand hover:decoration-2',
|
|
className
|
|
)}
|
|
{...props}
|
|
/>
|
|
),
|
|
p: ({ className, ...props }: React.HTMLAttributes<HTMLParagraphElement>) => (
|
|
<p className={cn('leading-7 not-first:mt-6 text-foreground-light', className)} {...props} />
|
|
),
|
|
ul: ({ className, ...props }: React.HTMLAttributes<HTMLUListElement>) => (
|
|
<ul className={cn('my-6 ml-6 list-disc text-foreground-light', className)} {...props} />
|
|
),
|
|
ol: ({ className, ...props }: React.HTMLAttributes<HTMLOListElement>) => (
|
|
<ol className={cn('my-6 ml-6 list-decimal text-foreground-light', className)} {...props} />
|
|
),
|
|
li: ({ className, ...props }: React.HTMLAttributes<HTMLElement>) => (
|
|
<li className={cn('mt-2', className)} {...props} />
|
|
),
|
|
blockquote: ({ className, ...props }: React.HTMLAttributes<HTMLElement>) => (
|
|
<blockquote className={cn('mt-6 border-l-2 pl-6 italic', className)} {...props} />
|
|
),
|
|
img: ({ className, alt, ...props }: React.ImgHTMLAttributes<HTMLImageElement>) => (
|
|
// eslint-disable-next-line @next/next/no-img-element
|
|
<img className={cn('rounded-md', className)} alt={alt} {...props} />
|
|
),
|
|
hr: ({ ...props }: React.HTMLAttributes<HTMLHRElement>) => (
|
|
<hr className="my-4 md:my-8" {...props} />
|
|
),
|
|
table: ({ className, ...props }: React.HTMLAttributes<HTMLTableElement>) => (
|
|
<div className="my-6 w-full overflow-y-auto">
|
|
<table className={cn('w-full', className)} {...props} />
|
|
</div>
|
|
),
|
|
tr: ({ className, ...props }: React.HTMLAttributes<HTMLTableRowElement>) => (
|
|
<tr className={cn('m-0 border-t p-0 even:bg-surface-75/75', className)} {...props} />
|
|
),
|
|
th: ({ className, ...props }: React.HTMLAttributes<HTMLTableCellElement>) => (
|
|
<th
|
|
className={cn(
|
|
'border px-4 py-2 text-left font-normal [[align=center]]:text-center [[align=right]]:text-right',
|
|
className
|
|
)}
|
|
{...props}
|
|
/>
|
|
),
|
|
td: ({ className, ...props }: React.HTMLAttributes<HTMLTableCellElement>) => (
|
|
<td
|
|
className={cn(
|
|
'border text-foreground-light px-4 py-2 text-left [[align=center]]:text-center [[align=right]]:text-right',
|
|
className
|
|
)}
|
|
{...props}
|
|
/>
|
|
),
|
|
pre: ({
|
|
className,
|
|
__rawString__,
|
|
__withMeta__,
|
|
__src__,
|
|
__style__,
|
|
...props
|
|
}: React.HTMLAttributes<HTMLPreElement> & {
|
|
__style__?: Style['name']
|
|
__rawString__?: string
|
|
__withMeta__?: boolean
|
|
__src__?: string
|
|
}) => {
|
|
return (
|
|
<StyleWrapper styleName={__style__}>
|
|
<pre
|
|
className={cn(
|
|
'mb-4 mt-6 max-h-[650px] overflow-x-auto rounded-lg border bg-surface-75/75 py-4 text-foreground-light',
|
|
className
|
|
)}
|
|
{...props}
|
|
/>
|
|
{__rawString__ && (
|
|
<CopyButton
|
|
value={__rawString__}
|
|
src={__src__}
|
|
className={cn('absolute right-4 top-4', __withMeta__ && 'top-16')}
|
|
/>
|
|
)}
|
|
</StyleWrapper>
|
|
)
|
|
},
|
|
code: ({ className, ...props }: React.HTMLAttributes<HTMLElement>) => (
|
|
<code
|
|
className={cn(
|
|
'relative rounded-sm bg-muted px-[0.3rem] py-[0.2rem] font-mono text-sm',
|
|
className
|
|
)}
|
|
{...props}
|
|
/>
|
|
),
|
|
Callout,
|
|
ComponentPreview,
|
|
CopyButton,
|
|
TanStackBeta,
|
|
Card: ({ className, ...props }: React.HTMLAttributes<HTMLElement>) => (
|
|
<div
|
|
className={cn(
|
|
'flex w-full flex-col items-center rounded-xl border bg-surface-100 text-card-background py-6 px-4 shadow-sm transition-colors hover:bg-muted/50 sm:p-10',
|
|
className
|
|
)}
|
|
{...props}
|
|
/>
|
|
),
|
|
LinkedCard: ({ className, ...props }: React.ComponentProps<typeof Link>) => (
|
|
<Link
|
|
className={cn(
|
|
'flex w-full flex-col items-center justify-center rounded-xl border bg-surface-100 text-card-background py-6 px-4 shadow-sm transition-colors hover:bg-muted/50 sm:p-10 h-52',
|
|
className
|
|
)}
|
|
{...props}
|
|
/>
|
|
),
|
|
BlockItem,
|
|
BlockPreview,
|
|
DualRealtimeChat,
|
|
DualRealtimeFlow,
|
|
DualRealtimeMonaco,
|
|
TanstackDBGenerator,
|
|
}
|
|
|
|
interface MdxProps {
|
|
code: string
|
|
}
|
|
|
|
export function Mdx({ code }: MdxProps) {
|
|
const Component = useMDXComponent(code, {
|
|
style: 'default',
|
|
})
|
|
|
|
return (
|
|
<div className="mdx">
|
|
<Component components={components} />
|
|
</div>
|
|
)
|
|
}
|