chore: migrate from next-mdx-remote to next-mdx-remote-client (#45149)

## Problem

We want to upgrade to react 19. However some libraries aren't compatible
with it. Besides, `next-mdx-remote` is now archived and not maintained
anymore.

## Solution

The [NextJS
documentation)[https://nextjs.org/docs/15/app/guides/mdx#remote-mdx]
suggest using
[`next-mdx-remote-client`](https://github.com/ipikuka/next-mdx-remote-client)
which was a fork of `next-mdx-remote`.

- [x] migrate `apps/www` from `next-mdx-remote` to
`next-mdx-remote-client`
- [x] migrate `apps/www` from `next-mdx-remote` to
`next-mdx-remote-client`

I haven't noticed any change in the pages.
When upgrading to react 19, we'll have to use v2 of
`next-mdx-remote-client`.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Refactor**
* Switched MDX rendering/serialization to a newer client-focused
implementation across docs and site for improved compatibility.

* **Bug Fixes**
* Improved handling of serialization errors so MDX failures render clear
fallback messages instead of breaking pages.

* **Chores**
* Updated local environment template value for the public anonymous key.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Gildas Garcia
2026-05-06 16:02:49 +02:00
committed by GitHub
parent f809d1c99a
commit 743d665dfe
30 changed files with 268 additions and 106 deletions

View File

@@ -3,14 +3,13 @@ import { components } from '~/features/docs/MdxBase.shared'
import { guidesData } from '~/lib/guidesData'
import { SerializeOptions } from '~/types/next-mdx-remote-serialize'
import { isFeatureEnabled } from 'common'
import { MDXRemote } from 'next-mdx-remote/rsc'
import { MDXRemote } from 'next-mdx-remote-client/rsc'
import { type ComponentProps } from 'react'
import rehypeKatex from 'rehype-katex'
import remarkGfm from 'remark-gfm'
import remarkMath from 'remark-math'
const mdxOptions: SerializeOptions = {
blockJS: false,
mdxOptions: {
remarkPlugins: [[remarkMath, { singleDollarTextMath: false }], remarkGfm],
rehypePlugins: [rehypeKatex as any],

View File

@@ -1,12 +1,12 @@
import matter from 'gray-matter'
import { serialize } from 'next-mdx-remote/serialize'
import { existsSync } from 'node:fs'
import { readdir, readFile } from 'node:fs/promises'
import { basename, extname, join, sep } from 'node:path'
import { type SerializeOptions } from '~/types/next-mdx-remote-serialize'
import matter from 'gray-matter'
import { serialize } from 'next-mdx-remote-client/serialize'
import rehypeKatex from 'rehype-katex'
import remarkGfm from 'remark-gfm'
import remarkMath from 'remark-math'
import { type SerializeOptions } from '~/types/next-mdx-remote-serialize'
// MUST be process.cwd() here, not import.meta.url, or files that are added
// with outputFileTracingIncludes (not auto-traced) will not be found at
@@ -125,14 +125,13 @@ export async function getGuidesStaticProps(
return
}
const mdxOptions: SerializeOptions = {
blockJS: false,
const options: SerializeOptions = {
mdxOptions: {
remarkPlugins: [[remarkMath, { singleDollarTextMath: false }], remarkGfm],
rehypePlugins: [rehypeKatex as any],
},
}
const mdxSource = await serialize(content, mdxOptions)
const mdxSource = await serialize({ source: content, options: options })
return {
props: {

View File

@@ -1,10 +1,9 @@
import fs from 'fs'
import type { ICommonMarkdown } from '~/components/reference/Reference.types'
import codeHikeTheme from 'config/code-hike.theme.json' with { type: 'json' }
import matter from 'gray-matter'
import { serialize } from 'next-mdx-remote/serialize'
import { serialize } from 'next-mdx-remote-client/serialize'
import remarkGfm from 'remark-gfm'
import type { ICommonMarkdown } from '~/components/reference/Reference.types'
async function generateRefMarkdown(sections: ICommonMarkdown[], slug: string) {
let markdownContent: any[] = []
@@ -39,12 +38,14 @@ async function generateRefMarkdown(sections: ICommonMarkdown[], slug: string) {
meta: data,
// introPage: introPages.includes(x),
content: content
? await serialize(content ?? '', {
blockJS: false,
// MDX's available options, see the MDX docs for more info.
// https://mdxjs.com/packages/mdx/#compilefile-options
mdxOptions: {
remarkPlugins: [remarkGfm],
? await serialize({
source: content ?? '',
options: {
// MDX's available options, see the MDX docs for more info.
// https://mdxjs.com/packages/mdx/#compilefile-options
mdxOptions: {
remarkPlugins: [remarkGfm],
},
},
})
: null,

View File

@@ -91,7 +91,7 @@
"micromark-extension-gfm": "^2.0.3",
"micromark-extension-mdxjs": "^1.0.0",
"next": "^15.5.15",
"next-mdx-remote": "^6.0.0",
"next-mdx-remote-client": "^1.1.7",
"next-plugin-yaml": "^1.0.1",
"next-themes": "catalog:",
"nuqs": "^1.19.1",

View File

@@ -1,5 +1,5 @@
import { serialize } from 'next-mdx-remote/serialize'
import { SerializeOptions as NextMdxRemoteSerializeOptions } from 'next-mdx-remote-client/serialize'
// The SerializeOptions is not exported from next-mdx-remote/serialize, so we need to
// manually define it here.
export type SerializeOptions = Parameters<typeof serialize>[1]
export type SerializeOptions = NextMdxRemoteSerializeOptions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -15,7 +15,7 @@
"files": [
{
"path": "registry/default/blocks/realtime-avatar-stack/components/avatar-stack.tsx",
"content": "import { cva, type VariantProps } from 'class-variance-authority'\nimport * as React from 'react'\n\nimport { cn } from '@/lib/utils'\nimport { Avatar, AvatarFallback, AvatarImage } from '@/registry/default/components/ui/avatar'\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/registry/default/components/ui/tooltip'\n\nconst avatarStackVariants = cva('flex -space-x-4 -space-y-4', {\n variants: {\n orientation: {\n vertical: 'flex-row',\n horizontal: 'flex-col',\n },\n },\n defaultVariants: {\n orientation: 'vertical',\n },\n})\n\nexport interface AvatarStackProps\n extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof avatarStackVariants> {\n avatars: { name: string; image: string }[]\n maxAvatarsAmount?: number\n}\n\nconst AvatarStack = ({\n className,\n orientation,\n avatars,\n maxAvatarsAmount = 3,\n ...props\n}: AvatarStackProps) => {\n const shownAvatars = avatars.slice(0, maxAvatarsAmount)\n const hiddenAvatars = avatars.slice(maxAvatarsAmount)\n\n return (\n <div\n className={cn(\n avatarStackVariants({ orientation }),\n className,\n orientation === 'horizontal' ? '-space-x-0' : '-space-y-0'\n )}\n {...props}\n >\n {shownAvatars.map(({ name, image }, index) => (\n <Tooltip key={`${name}-${image}-${index}`}>\n <TooltipTrigger asChild>\n <Avatar className=\"hover:z-10\">\n <AvatarImage src={image} />\n <AvatarFallback>\n {name\n ?.split(' ')\n ?.map((word) => word[0])\n ?.join('')\n ?.toUpperCase()}\n </AvatarFallback>\n </Avatar>\n </TooltipTrigger>\n <TooltipContent>\n <p>{name}</p>\n </TooltipContent>\n </Tooltip>\n ))}\n\n {hiddenAvatars.length ? (\n <Tooltip key=\"hidden-avatars\">\n <TooltipTrigger asChild>\n <Avatar>\n <AvatarFallback>+{avatars.length - shownAvatars.length}</AvatarFallback>\n </Avatar>\n </TooltipTrigger>\n <TooltipContent>\n {hiddenAvatars.map(({ name }, index) => (\n <p key={`${name}-${index}`}>{name}</p>\n ))}\n </TooltipContent>\n </Tooltip>\n ) : null}\n </div>\n )\n}\n\nexport { AvatarStack, avatarStackVariants }\n",
"content": "import { cva, type VariantProps } from 'class-variance-authority'\nimport * as React from 'react'\n\nimport { cn } from '@/lib/utils'\nimport { Avatar, AvatarFallback, AvatarImage } from '@/registry/default/components/ui/avatar'\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/registry/default/components/ui/tooltip'\n\nconst avatarStackVariants = cva('flex -space-x-4 -space-y-4', {\n variants: {\n orientation: {\n vertical: 'flex-row',\n horizontal: 'flex-col',\n },\n },\n defaultVariants: {\n orientation: 'vertical',\n },\n})\n\nexport interface AvatarStackProps\n extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof avatarStackVariants> {\n avatars: { name: string; image: string }[]\n maxAvatarsAmount?: number\n}\n\nconst AvatarStack = ({\n className,\n orientation,\n avatars,\n maxAvatarsAmount = 3,\n ...props\n}: AvatarStackProps) => {\n const shownAvatars = avatars.slice(0, maxAvatarsAmount)\n const hiddenAvatars = avatars.slice(maxAvatarsAmount)\n\n return (\n <div\n className={cn(\n avatarStackVariants({ orientation }),\n className,\n orientation === 'horizontal' ? 'space-x-0' : 'space-y-0'\n )}\n {...props}\n >\n {shownAvatars.map(({ name, image }, index) => (\n <Tooltip key={`${name}-${image}-${index}`}>\n <TooltipTrigger asChild>\n <Avatar className=\"hover:z-10\">\n <AvatarImage src={image} />\n <AvatarFallback>\n {name\n ?.split(' ')\n ?.map((word) => word[0])\n ?.join('')\n ?.toUpperCase()}\n </AvatarFallback>\n </Avatar>\n </TooltipTrigger>\n <TooltipContent>\n <p>{name}</p>\n </TooltipContent>\n </Tooltip>\n ))}\n\n {hiddenAvatars.length ? (\n <Tooltip key=\"hidden-avatars\">\n <TooltipTrigger asChild>\n <Avatar>\n <AvatarFallback>+{avatars.length - shownAvatars.length}</AvatarFallback>\n </Avatar>\n </TooltipTrigger>\n <TooltipContent>\n {hiddenAvatars.map(({ name }, index) => (\n <p key={`${name}-${index}`}>{name}</p>\n ))}\n </TooltipContent>\n </Tooltip>\n ) : null}\n </div>\n )\n}\n\nexport { AvatarStack, avatarStackVariants }\n",
"type": "registry:component"
},
{

View File

@@ -15,7 +15,7 @@
"files": [
{
"path": "registry/default/blocks/realtime-avatar-stack/components/avatar-stack.tsx",
"content": "import { cva, type VariantProps } from 'class-variance-authority'\nimport * as React from 'react'\n\nimport { cn } from '@/lib/utils'\nimport { Avatar, AvatarFallback, AvatarImage } from '@/registry/default/components/ui/avatar'\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/registry/default/components/ui/tooltip'\n\nconst avatarStackVariants = cva('flex -space-x-4 -space-y-4', {\n variants: {\n orientation: {\n vertical: 'flex-row',\n horizontal: 'flex-col',\n },\n },\n defaultVariants: {\n orientation: 'vertical',\n },\n})\n\nexport interface AvatarStackProps\n extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof avatarStackVariants> {\n avatars: { name: string; image: string }[]\n maxAvatarsAmount?: number\n}\n\nconst AvatarStack = ({\n className,\n orientation,\n avatars,\n maxAvatarsAmount = 3,\n ...props\n}: AvatarStackProps) => {\n const shownAvatars = avatars.slice(0, maxAvatarsAmount)\n const hiddenAvatars = avatars.slice(maxAvatarsAmount)\n\n return (\n <div\n className={cn(\n avatarStackVariants({ orientation }),\n className,\n orientation === 'horizontal' ? '-space-x-0' : '-space-y-0'\n )}\n {...props}\n >\n {shownAvatars.map(({ name, image }, index) => (\n <Tooltip key={`${name}-${image}-${index}`}>\n <TooltipTrigger asChild>\n <Avatar className=\"hover:z-10\">\n <AvatarImage src={image} />\n <AvatarFallback>\n {name\n ?.split(' ')\n ?.map((word) => word[0])\n ?.join('')\n ?.toUpperCase()}\n </AvatarFallback>\n </Avatar>\n </TooltipTrigger>\n <TooltipContent>\n <p>{name}</p>\n </TooltipContent>\n </Tooltip>\n ))}\n\n {hiddenAvatars.length ? (\n <Tooltip key=\"hidden-avatars\">\n <TooltipTrigger asChild>\n <Avatar>\n <AvatarFallback>+{avatars.length - shownAvatars.length}</AvatarFallback>\n </Avatar>\n </TooltipTrigger>\n <TooltipContent>\n {hiddenAvatars.map(({ name }, index) => (\n <p key={`${name}-${index}`}>{name}</p>\n ))}\n </TooltipContent>\n </Tooltip>\n ) : null}\n </div>\n )\n}\n\nexport { AvatarStack, avatarStackVariants }\n",
"content": "import { cva, type VariantProps } from 'class-variance-authority'\nimport * as React from 'react'\n\nimport { cn } from '@/lib/utils'\nimport { Avatar, AvatarFallback, AvatarImage } from '@/registry/default/components/ui/avatar'\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/registry/default/components/ui/tooltip'\n\nconst avatarStackVariants = cva('flex -space-x-4 -space-y-4', {\n variants: {\n orientation: {\n vertical: 'flex-row',\n horizontal: 'flex-col',\n },\n },\n defaultVariants: {\n orientation: 'vertical',\n },\n})\n\nexport interface AvatarStackProps\n extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof avatarStackVariants> {\n avatars: { name: string; image: string }[]\n maxAvatarsAmount?: number\n}\n\nconst AvatarStack = ({\n className,\n orientation,\n avatars,\n maxAvatarsAmount = 3,\n ...props\n}: AvatarStackProps) => {\n const shownAvatars = avatars.slice(0, maxAvatarsAmount)\n const hiddenAvatars = avatars.slice(maxAvatarsAmount)\n\n return (\n <div\n className={cn(\n avatarStackVariants({ orientation }),\n className,\n orientation === 'horizontal' ? 'space-x-0' : 'space-y-0'\n )}\n {...props}\n >\n {shownAvatars.map(({ name, image }, index) => (\n <Tooltip key={`${name}-${image}-${index}`}>\n <TooltipTrigger asChild>\n <Avatar className=\"hover:z-10\">\n <AvatarImage src={image} />\n <AvatarFallback>\n {name\n ?.split(' ')\n ?.map((word) => word[0])\n ?.join('')\n ?.toUpperCase()}\n </AvatarFallback>\n </Avatar>\n </TooltipTrigger>\n <TooltipContent>\n <p>{name}</p>\n </TooltipContent>\n </Tooltip>\n ))}\n\n {hiddenAvatars.length ? (\n <Tooltip key=\"hidden-avatars\">\n <TooltipTrigger asChild>\n <Avatar>\n <AvatarFallback>+{avatars.length - shownAvatars.length}</AvatarFallback>\n </Avatar>\n </TooltipTrigger>\n <TooltipContent>\n {hiddenAvatars.map(({ name }, index) => (\n <p key={`${name}-${index}`}>{name}</p>\n ))}\n </TooltipContent>\n </Tooltip>\n ) : null}\n </div>\n )\n}\n\nexport { AvatarStack, avatarStackVariants }\n",
"type": "registry:component"
},
{

View File

@@ -14,7 +14,7 @@
"files": [
{
"path": "registry/default/blocks/realtime-avatar-stack/components/avatar-stack.tsx",
"content": "import { cva, type VariantProps } from 'class-variance-authority'\nimport * as React from 'react'\n\nimport { cn } from '@/lib/utils'\nimport { Avatar, AvatarFallback, AvatarImage } from '@/registry/default/components/ui/avatar'\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/registry/default/components/ui/tooltip'\n\nconst avatarStackVariants = cva('flex -space-x-4 -space-y-4', {\n variants: {\n orientation: {\n vertical: 'flex-row',\n horizontal: 'flex-col',\n },\n },\n defaultVariants: {\n orientation: 'vertical',\n },\n})\n\nexport interface AvatarStackProps\n extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof avatarStackVariants> {\n avatars: { name: string; image: string }[]\n maxAvatarsAmount?: number\n}\n\nconst AvatarStack = ({\n className,\n orientation,\n avatars,\n maxAvatarsAmount = 3,\n ...props\n}: AvatarStackProps) => {\n const shownAvatars = avatars.slice(0, maxAvatarsAmount)\n const hiddenAvatars = avatars.slice(maxAvatarsAmount)\n\n return (\n <div\n className={cn(\n avatarStackVariants({ orientation }),\n className,\n orientation === 'horizontal' ? '-space-x-0' : '-space-y-0'\n )}\n {...props}\n >\n {shownAvatars.map(({ name, image }, index) => (\n <Tooltip key={`${name}-${image}-${index}`}>\n <TooltipTrigger asChild>\n <Avatar className=\"hover:z-10\">\n <AvatarImage src={image} />\n <AvatarFallback>\n {name\n ?.split(' ')\n ?.map((word) => word[0])\n ?.join('')\n ?.toUpperCase()}\n </AvatarFallback>\n </Avatar>\n </TooltipTrigger>\n <TooltipContent>\n <p>{name}</p>\n </TooltipContent>\n </Tooltip>\n ))}\n\n {hiddenAvatars.length ? (\n <Tooltip key=\"hidden-avatars\">\n <TooltipTrigger asChild>\n <Avatar>\n <AvatarFallback>+{avatars.length - shownAvatars.length}</AvatarFallback>\n </Avatar>\n </TooltipTrigger>\n <TooltipContent>\n {hiddenAvatars.map(({ name }, index) => (\n <p key={`${name}-${index}`}>{name}</p>\n ))}\n </TooltipContent>\n </Tooltip>\n ) : null}\n </div>\n )\n}\n\nexport { AvatarStack, avatarStackVariants }\n",
"content": "import { cva, type VariantProps } from 'class-variance-authority'\nimport * as React from 'react'\n\nimport { cn } from '@/lib/utils'\nimport { Avatar, AvatarFallback, AvatarImage } from '@/registry/default/components/ui/avatar'\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/registry/default/components/ui/tooltip'\n\nconst avatarStackVariants = cva('flex -space-x-4 -space-y-4', {\n variants: {\n orientation: {\n vertical: 'flex-row',\n horizontal: 'flex-col',\n },\n },\n defaultVariants: {\n orientation: 'vertical',\n },\n})\n\nexport interface AvatarStackProps\n extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof avatarStackVariants> {\n avatars: { name: string; image: string }[]\n maxAvatarsAmount?: number\n}\n\nconst AvatarStack = ({\n className,\n orientation,\n avatars,\n maxAvatarsAmount = 3,\n ...props\n}: AvatarStackProps) => {\n const shownAvatars = avatars.slice(0, maxAvatarsAmount)\n const hiddenAvatars = avatars.slice(maxAvatarsAmount)\n\n return (\n <div\n className={cn(\n avatarStackVariants({ orientation }),\n className,\n orientation === 'horizontal' ? 'space-x-0' : 'space-y-0'\n )}\n {...props}\n >\n {shownAvatars.map(({ name, image }, index) => (\n <Tooltip key={`${name}-${image}-${index}`}>\n <TooltipTrigger asChild>\n <Avatar className=\"hover:z-10\">\n <AvatarImage src={image} />\n <AvatarFallback>\n {name\n ?.split(' ')\n ?.map((word) => word[0])\n ?.join('')\n ?.toUpperCase()}\n </AvatarFallback>\n </Avatar>\n </TooltipTrigger>\n <TooltipContent>\n <p>{name}</p>\n </TooltipContent>\n </Tooltip>\n ))}\n\n {hiddenAvatars.length ? (\n <Tooltip key=\"hidden-avatars\">\n <TooltipTrigger asChild>\n <Avatar>\n <AvatarFallback>+{avatars.length - shownAvatars.length}</AvatarFallback>\n </Avatar>\n </TooltipTrigger>\n <TooltipContent>\n {hiddenAvatars.map(({ name }, index) => (\n <p key={`${name}-${index}`}>{name}</p>\n ))}\n </TooltipContent>\n </Tooltip>\n ) : null}\n </div>\n )\n}\n\nexport { AvatarStack, avatarStackVariants }\n",
"type": "registry:component"
},
{

View File

@@ -15,7 +15,7 @@
"files": [
{
"path": "registry/default/blocks/realtime-avatar-stack/components/avatar-stack.tsx",
"content": "import { cva, type VariantProps } from 'class-variance-authority'\nimport * as React from 'react'\n\nimport { cn } from '@/lib/utils'\nimport { Avatar, AvatarFallback, AvatarImage } from '@/registry/default/components/ui/avatar'\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/registry/default/components/ui/tooltip'\n\nconst avatarStackVariants = cva('flex -space-x-4 -space-y-4', {\n variants: {\n orientation: {\n vertical: 'flex-row',\n horizontal: 'flex-col',\n },\n },\n defaultVariants: {\n orientation: 'vertical',\n },\n})\n\nexport interface AvatarStackProps\n extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof avatarStackVariants> {\n avatars: { name: string; image: string }[]\n maxAvatarsAmount?: number\n}\n\nconst AvatarStack = ({\n className,\n orientation,\n avatars,\n maxAvatarsAmount = 3,\n ...props\n}: AvatarStackProps) => {\n const shownAvatars = avatars.slice(0, maxAvatarsAmount)\n const hiddenAvatars = avatars.slice(maxAvatarsAmount)\n\n return (\n <div\n className={cn(\n avatarStackVariants({ orientation }),\n className,\n orientation === 'horizontal' ? '-space-x-0' : '-space-y-0'\n )}\n {...props}\n >\n {shownAvatars.map(({ name, image }, index) => (\n <Tooltip key={`${name}-${image}-${index}`}>\n <TooltipTrigger asChild>\n <Avatar className=\"hover:z-10\">\n <AvatarImage src={image} />\n <AvatarFallback>\n {name\n ?.split(' ')\n ?.map((word) => word[0])\n ?.join('')\n ?.toUpperCase()}\n </AvatarFallback>\n </Avatar>\n </TooltipTrigger>\n <TooltipContent>\n <p>{name}</p>\n </TooltipContent>\n </Tooltip>\n ))}\n\n {hiddenAvatars.length ? (\n <Tooltip key=\"hidden-avatars\">\n <TooltipTrigger asChild>\n <Avatar>\n <AvatarFallback>+{avatars.length - shownAvatars.length}</AvatarFallback>\n </Avatar>\n </TooltipTrigger>\n <TooltipContent>\n {hiddenAvatars.map(({ name }, index) => (\n <p key={`${name}-${index}`}>{name}</p>\n ))}\n </TooltipContent>\n </Tooltip>\n ) : null}\n </div>\n )\n}\n\nexport { AvatarStack, avatarStackVariants }\n",
"content": "import { cva, type VariantProps } from 'class-variance-authority'\nimport * as React from 'react'\n\nimport { cn } from '@/lib/utils'\nimport { Avatar, AvatarFallback, AvatarImage } from '@/registry/default/components/ui/avatar'\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/registry/default/components/ui/tooltip'\n\nconst avatarStackVariants = cva('flex -space-x-4 -space-y-4', {\n variants: {\n orientation: {\n vertical: 'flex-row',\n horizontal: 'flex-col',\n },\n },\n defaultVariants: {\n orientation: 'vertical',\n },\n})\n\nexport interface AvatarStackProps\n extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof avatarStackVariants> {\n avatars: { name: string; image: string }[]\n maxAvatarsAmount?: number\n}\n\nconst AvatarStack = ({\n className,\n orientation,\n avatars,\n maxAvatarsAmount = 3,\n ...props\n}: AvatarStackProps) => {\n const shownAvatars = avatars.slice(0, maxAvatarsAmount)\n const hiddenAvatars = avatars.slice(maxAvatarsAmount)\n\n return (\n <div\n className={cn(\n avatarStackVariants({ orientation }),\n className,\n orientation === 'horizontal' ? 'space-x-0' : 'space-y-0'\n )}\n {...props}\n >\n {shownAvatars.map(({ name, image }, index) => (\n <Tooltip key={`${name}-${image}-${index}`}>\n <TooltipTrigger asChild>\n <Avatar className=\"hover:z-10\">\n <AvatarImage src={image} />\n <AvatarFallback>\n {name\n ?.split(' ')\n ?.map((word) => word[0])\n ?.join('')\n ?.toUpperCase()}\n </AvatarFallback>\n </Avatar>\n </TooltipTrigger>\n <TooltipContent>\n <p>{name}</p>\n </TooltipContent>\n </Tooltip>\n ))}\n\n {hiddenAvatars.length ? (\n <Tooltip key=\"hidden-avatars\">\n <TooltipTrigger asChild>\n <Avatar>\n <AvatarFallback>+{avatars.length - shownAvatars.length}</AvatarFallback>\n </Avatar>\n </TooltipTrigger>\n <TooltipContent>\n {hiddenAvatars.map(({ name }, index) => (\n <p key={`${name}-${index}`}>{name}</p>\n ))}\n </TooltipContent>\n </Tooltip>\n ) : null}\n </div>\n )\n}\n\nexport { AvatarStack, avatarStackVariants }\n",
"type": "registry:component"
},
{

View File

@@ -13,7 +13,7 @@
"files": [
{
"path": "registry/default/blocks/realtime-cursor/components/cursor.tsx",
"content": "import { MousePointer2 } from 'lucide-react'\n\nimport { cn } from '@/lib/utils'\n\nexport const Cursor = ({\n className,\n style,\n color,\n name,\n}: {\n className?: string\n style?: React.CSSProperties\n color: string\n name: string\n}) => {\n return (\n <div className={cn('pointer-events-none', className)} style={style}>\n <MousePointer2 color={color} fill={color} size={30} />\n\n <div\n className=\"mt-1 px-2 py-1 rounded text-xs font-bold text-white text-center\"\n style={{ backgroundColor: color }}\n >\n {name}\n </div>\n </div>\n )\n}\n",
"content": "import { MousePointer2 } from 'lucide-react'\n\nimport { cn } from '@/lib/utils'\n\nexport const Cursor = ({\n className,\n style,\n color,\n name,\n}: {\n className?: string\n style?: React.CSSProperties\n color: string\n name: string\n}) => {\n return (\n <div className={cn('pointer-events-none', className)} style={style}>\n <MousePointer2 color={color} fill={color} size={30} />\n\n <div\n className=\"mt-1 px-2 py-1 rounded-sm text-xs font-bold text-white text-center\"\n style={{ backgroundColor: color }}\n >\n {name}\n </div>\n </div>\n )\n}\n",
"type": "registry:component"
},
{

View File

@@ -13,7 +13,7 @@
"files": [
{
"path": "registry/default/blocks/realtime-cursor/components/cursor.tsx",
"content": "import { MousePointer2 } from 'lucide-react'\n\nimport { cn } from '@/lib/utils'\n\nexport const Cursor = ({\n className,\n style,\n color,\n name,\n}: {\n className?: string\n style?: React.CSSProperties\n color: string\n name: string\n}) => {\n return (\n <div className={cn('pointer-events-none', className)} style={style}>\n <MousePointer2 color={color} fill={color} size={30} />\n\n <div\n className=\"mt-1 px-2 py-1 rounded text-xs font-bold text-white text-center\"\n style={{ backgroundColor: color }}\n >\n {name}\n </div>\n </div>\n )\n}\n",
"content": "import { MousePointer2 } from 'lucide-react'\n\nimport { cn } from '@/lib/utils'\n\nexport const Cursor = ({\n className,\n style,\n color,\n name,\n}: {\n className?: string\n style?: React.CSSProperties\n color: string\n name: string\n}) => {\n return (\n <div className={cn('pointer-events-none', className)} style={style}>\n <MousePointer2 color={color} fill={color} size={30} />\n\n <div\n className=\"mt-1 px-2 py-1 rounded-sm text-xs font-bold text-white text-center\"\n style={{ backgroundColor: color }}\n >\n {name}\n </div>\n </div>\n )\n}\n",
"type": "registry:component"
},
{

View File

@@ -12,7 +12,7 @@
"files": [
{
"path": "registry/default/blocks/realtime-cursor/components/cursor.tsx",
"content": "import { MousePointer2 } from 'lucide-react'\n\nimport { cn } from '@/lib/utils'\n\nexport const Cursor = ({\n className,\n style,\n color,\n name,\n}: {\n className?: string\n style?: React.CSSProperties\n color: string\n name: string\n}) => {\n return (\n <div className={cn('pointer-events-none', className)} style={style}>\n <MousePointer2 color={color} fill={color} size={30} />\n\n <div\n className=\"mt-1 px-2 py-1 rounded text-xs font-bold text-white text-center\"\n style={{ backgroundColor: color }}\n >\n {name}\n </div>\n </div>\n )\n}\n",
"content": "import { MousePointer2 } from 'lucide-react'\n\nimport { cn } from '@/lib/utils'\n\nexport const Cursor = ({\n className,\n style,\n color,\n name,\n}: {\n className?: string\n style?: React.CSSProperties\n color: string\n name: string\n}) => {\n return (\n <div className={cn('pointer-events-none', className)} style={style}>\n <MousePointer2 color={color} fill={color} size={30} />\n\n <div\n className=\"mt-1 px-2 py-1 rounded-sm text-xs font-bold text-white text-center\"\n style={{ backgroundColor: color }}\n >\n {name}\n </div>\n </div>\n )\n}\n",
"type": "registry:component"
},
{

View File

@@ -13,7 +13,7 @@
"files": [
{
"path": "registry/default/blocks/realtime-cursor/components/cursor.tsx",
"content": "import { MousePointer2 } from 'lucide-react'\n\nimport { cn } from '@/lib/utils'\n\nexport const Cursor = ({\n className,\n style,\n color,\n name,\n}: {\n className?: string\n style?: React.CSSProperties\n color: string\n name: string\n}) => {\n return (\n <div className={cn('pointer-events-none', className)} style={style}>\n <MousePointer2 color={color} fill={color} size={30} />\n\n <div\n className=\"mt-1 px-2 py-1 rounded text-xs font-bold text-white text-center\"\n style={{ backgroundColor: color }}\n >\n {name}\n </div>\n </div>\n )\n}\n",
"content": "import { MousePointer2 } from 'lucide-react'\n\nimport { cn } from '@/lib/utils'\n\nexport const Cursor = ({\n className,\n style,\n color,\n name,\n}: {\n className?: string\n style?: React.CSSProperties\n color: string\n name: string\n}) => {\n return (\n <div className={cn('pointer-events-none', className)} style={style}>\n <MousePointer2 color={color} fill={color} size={30} />\n\n <div\n className=\"mt-1 px-2 py-1 rounded-sm text-xs font-bold text-white text-center\"\n style={{ backgroundColor: color }}\n >\n {name}\n </div>\n </div>\n )\n}\n",
"type": "registry:component"
},
{

View File

@@ -9,7 +9,7 @@ NEXT_PUBLIC_DOCS_URL=http://localhost:3005
NEXT_PUBLIC_ENVIRONMENT=local
NEXT_PUBLIC_HCAPTCHA_SITE_KEY=10000000-ffff-ffff-ffff-000000000001
NEXT_PUBLIC_IS_PLATFORM=true
NEXT_PUBLIC_MISC_USE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Im9idWxkYW5ycHRsb2t0eGNmZnZuIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MTg2MTQ2ODUsImV4cCI6MjAzNDE5MDY4NX0.NFt49g6DFkc1X5khCzN5p01iAVo2TMxlx88cY1V0E2M
NEXT_PUBLIC_MISC_USE_ANON_KEY=sb_publishable_t45SVhgymMJOuamUXzJzPQ_sY-tSoUr
NEXT_PUBLIC_MISC_USE_URL=https://obuldanrptloktxcffvn.supabase.co
NEXT_PUBLIC_POSTHOG_HOST=https://ph.supabase.green
NEXT_PUBLIC_POSTHOG_KEY=your-posthog-key-here

View File

@@ -1,13 +1,13 @@
import authors from 'lib/authors.json'
import { MDXRemote } from 'next-mdx-remote'
import { NextSeo } from 'next-seo'
import Image from 'next/image'
import Link from 'next/link'
import React from 'react'
import CTABanner from '~/components/CTABanner'
import DefaultLayout from '~/components/Layouts/Default'
import { getAbsoluteBlogSocialImage } from '~/lib/blog-images'
import { generateReadingTime } from '~/lib/helpers'
import authors from 'lib/authors.json'
import { MDXClient } from 'next-mdx-remote-client/csr'
import { NextSeo } from 'next-seo'
import Image from 'next/image'
import Link from 'next/link'
import React from 'react'
interface Props {
components: React.ReactNode
@@ -125,7 +125,7 @@ const LayoutComparison = ({ components, props }: Props) => {
<div>
{/* Content */}
<div className="prose prose-docs max-w-none">
<MDXRemote {...content} components={components} />
<MDXClient {...content} components={components} />
</div>
<div className="py-16">
<div className="text-foreground-lighter text-sm">Share this article</div>

View File

@@ -1,6 +1,6 @@
import { remarkCodeHike, type CodeHikeConfig } from '@code-hike/mdx'
import codeHikeTheme from 'config/code-hike.theme.json' with { type: 'json' }
import type { MDXRemoteProps } from 'next-mdx-remote/rsc'
import type { SerializeOptions } from 'next-mdx-remote-client/serialize'
import rehypeSlug from 'rehype-slug'
import remarkGfm from 'remark-gfm'
@@ -12,7 +12,7 @@ const codeHikeOptions: CodeHikeConfig = {
autoImport: false,
}
type MdxOptions = NonNullable<NonNullable<MDXRemoteProps['options']>['mdxOptions']>
type MdxOptions = NonNullable<SerializeOptions['mdxOptions']>
export const mdxOptionsBlog: MdxOptions = {
remarkPlugins: [remarkNormalizeHtmlImages, [remarkCodeHike, codeHikeOptions], remarkGfm],

View File

@@ -1,7 +1,7 @@
import { remarkCodeHike, type CodeHikeConfig } from '@code-hike/mdx'
import { preprocessMdxWithCodeTabs } from '~/components/CodeTabs'
import codeHikeTheme from 'config/code-hike.theme.json' with { type: 'json' }
import { serialize } from 'next-mdx-remote/serialize'
import { serialize } from 'next-mdx-remote-client/serialize'
import rehypeSlug from 'rehype-slug'
import remarkGfm from 'remark-gfm'
@@ -157,32 +157,34 @@ export async function mdxSerialize(source: string, options?: { tocDepth?: number
const tocDepth = options?.tocDepth ?? 2
let collectedToc: TocItem[] = []
const mdxSource = await serialize(preprocessedSource, {
blockJS: false,
scope: {
chCodeConfig: codeHikeOptions,
},
mdxOptions: {
remarkPlugins: [
remarkNormalizeHtmlImages,
[remarkCodeHike, codeHikeOptions],
remarkGfm,
// Collect headings into a simple TOC structure
() => {
const plugin = createRemarkCollectToc(tocDepth)
const transformer = (plugin as any)()
return (tree: any) => {
transformer(tree)
if (tree?.data?.__collectedToc) {
collectedToc = tree.data.__collectedToc as TocItem[]
const mdxSource = await serialize({
source: preprocessedSource,
options: {
scope: {
toc: { content: '', json: collectedToc },
},
mdxOptions: {
remarkPlugins: [
remarkNormalizeHtmlImages,
[remarkCodeHike, codeHikeOptions],
remarkGfm,
// Collect headings into a simple TOC structure
() => {
const plugin = createRemarkCollectToc(tocDepth)
const transformer = (plugin as any)()
return (tree: any) => {
transformer(tree)
if (tree?.data?.__collectedToc) {
collectedToc = tree.data.__collectedToc as TocItem[]
}
}
}
},
],
rehypePlugins: [
// @ts-ignore
rehypeSlug, // add IDs to any h1-h6 tag that doesn't have one, using a slug made from its text
],
},
],
rehypePlugins: [
// @ts-ignore
rehypeSlug, // add IDs to any h1-h6 tag that doesn't have one, using a slug made from its text
],
},
},
})

View File

@@ -65,7 +65,7 @@
"micromark-extension-gfm": "^2.0.3",
"micromark-extension-mdxjs": "^1.0.1",
"next": "^15.5.15",
"next-mdx-remote": "^6.0.0",
"next-mdx-remote-client": "^1.1.7",
"next-seo": "^6.5.0",
"next-themes": "catalog:",
"nuqs": "^2.8.1",

View File

@@ -2,8 +2,8 @@ import { useBreakpoint } from 'common'
import dayjs from 'dayjs'
import { GitCommit, ListFilter, Rss, X } from 'lucide-react'
import type { GetServerSideProps } from 'next'
import type { MDXRemoteSerializeResult } from 'next-mdx-remote'
import { MDXRemote } from 'next-mdx-remote'
import { MDXClient } from 'next-mdx-remote-client/csr'
import type { SerializeResult as MDXRemoteSerializeResult } from 'next-mdx-remote-client/serialize'
import { NextSeo } from 'next-seo'
import Head from 'next/head'
import Link from 'next/link'
@@ -393,7 +393,11 @@ function ChangelogIndex({ featured, restIndex, allIndex }: PageProps) {
</div>
<div className="col-span-8 lg:max-w-[calc(100vw-80px)]">
<article className="prose prose-docs max-w-none wrap-break-word [&>*:first-child:not(style):not(script)]:mt-0 [&>style:first-child+*]:mt-0 [&>script:first-child+*]:mt-0 [&>*:last-child:not(style):not(script)]:mb-0">
<MDXRemote {...entry.source} components={mdxComponents('blog')} />
{'error' in entry.source ? (
<p>Error rendering changelog: {entry.source.error.message}</p>
) : (
<MDXClient {...entry.source} components={mdxComponents('blog')} />
)}
</article>
</div>
</div>

View File

@@ -1,6 +1,6 @@
import dayjs from 'dayjs'
import type { GetStaticPaths, GetStaticProps } from 'next'
import { MDXRemote, type MDXRemoteSerializeResult } from 'next-mdx-remote'
import { MDXClient, type SerializeResult as MDXRemoteSerializeResult } from 'next-mdx-remote-client'
import { NextSeo } from 'next-seo'
import Head from 'next/head'
import Link from 'next/link'
@@ -62,7 +62,11 @@ const ChangelogDetailPage = ({ title, url, created_at, slug, source, labels }: P
<div className="grid grid-cols-1 gap-8 lg:grid-cols-12 lg:gap-10 mb-8 lg:mb-20">
<div className="min-w-0 lg:col-span-8">
<article className="prose prose-docs max-w-none wrap-break-word [&>*:first-child:not(style):not(script)]:mt-0 [&>style:first-child+*]:mt-0 [&>script:first-child+*]:mt-0 [&>*:last-child:not(style):not(script)]:mb-0">
<MDXRemote {...source} components={mdxComponents('blog')} />
{'error' in source ? (
<p>Error rendering blog post: {source.error.message}</p>
) : (
<MDXClient {...source} components={mdxComponents('blog')} />
)}
</article>
</div>

View File

@@ -8,7 +8,7 @@ import { mdxSerialize } from '~/lib/mdx/mdxSerialize'
import { getAllPostSlugs, getPostdata, getSortedPosts } from '~/lib/posts'
import matter from 'gray-matter'
import { ChevronLeft, ChevronRight, ExternalLink } from 'lucide-react'
import { MDXRemote } from 'next-mdx-remote'
import { MDXClient } from 'next-mdx-remote-client/csr'
import { NextSeo } from 'next-seo'
import Head from 'next/head'
import Image from 'next/image'
@@ -228,7 +228,7 @@ function CaseStudyPage(props: any) {
</div>
</div>
<div className="xm:col-span-7 col-span-12 lg:col-span-8 xl:col-span-8 ">
<MDXRemote {...content} components={mdxComponents()} />
<MDXClient {...content} components={mdxComponents()} />
</div>
</div>
</article>

View File

@@ -13,7 +13,7 @@ import utc from 'dayjs/plugin/utc'
import matter from 'gray-matter'
import { ChevronLeft, X as XIcon } from 'lucide-react'
import type { GetStaticProps, InferGetStaticPropsType } from 'next'
import { MDXRemote } from 'next-mdx-remote'
import { MDXClient } from 'next-mdx-remote-client/csr'
import { NextSeo } from 'next-seo'
import Head from 'next/head'
import NextImage from 'next/image'
@@ -388,7 +388,7 @@ const EventPage = ({ event }: InferGetStaticPropsType<typeof getStaticProps>) =>
<h2 className="text-foreground-light text-sm font-mono uppercase">
About this event
</h2>
<MDXRemote {...content} components={mdxComponents()} />
<MDXClient {...content} components={mdxComponents()} />
</div>
<aside className="mt-8">
<Button

View File

@@ -2,8 +2,9 @@ import { remarkCodeHike, type CodeHikeConfig } from '@code-hike/mdx'
import { CH } from '@code-hike/mdx/components'
import { ChevronLeft, ExternalLink } from 'lucide-react'
import { type GetStaticPaths, type GetStaticProps } from 'next'
import { MDXRemote, type MDXRemoteSerializeResult } from 'next-mdx-remote'
import { serialize } from 'next-mdx-remote/serialize'
import type { SerializeResult as MDXRemoteSerializeResult } from 'next-mdx-remote-client'
import { MDXClient } from 'next-mdx-remote-client/csr'
import { serialize } from 'next-mdx-remote-client/serialize'
import { NextSeo } from 'next-seo'
import Image from 'next/image'
import Link from 'next/link'
@@ -189,7 +190,11 @@ function Partner({
</h2>
<div className="prose">
<MDXRemote {...overview} components={mdxComponents(setFocusedImage)} />
{'error' in overview ? (
<p>Error rendering integration page: {overview.error.message}</p>
) : (
<MDXClient {...overview} components={mdxComponents(setFocusedImage)} />
)}
</div>
</div>
@@ -340,13 +345,12 @@ export const getStaticProps: GetStaticProps = async ({ params }) => {
}
// Parse markdown
const overview = await serialize(partner.overview, {
blockJS: false,
scope: {
chCodeConfig: codeHikeOptions,
},
mdxOptions: {
remarkPlugins: [remarkGfm, [remarkCodeHike, codeHikeOptions]],
const overview = await serialize({
source: partner.overview,
options: {
mdxOptions: {
remarkPlugins: [remarkGfm, [remarkCodeHike, codeHikeOptions]],
},
},
})

View File

@@ -1,3 +1,5 @@
import type { SerializeResult as MDXRemoteSerializeResult } from 'next-mdx-remote-client/serialize'
import type { getSortedPosts } from '@/lib/posts'
export interface PostTypes {

177
pnpm-lock.yaml generated
View File

@@ -461,9 +461,9 @@ importers:
next:
specifier: ^15.5.15
version: 15.5.15(@babel/core@7.29.0(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4)
next-mdx-remote:
specifier: ^6.0.0
version: 6.0.0(@types/react@18.3.3)(react@18.3.1)(supports-color@8.1.1)
next-mdx-remote-client:
specifier: ^1.1.7
version: 1.1.7(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(unified@11.0.5)
next-plugin-yaml:
specifier: ^1.0.1
version: 1.0.1
@@ -1723,9 +1723,9 @@ importers:
next:
specifier: ^15.5.15
version: 15.5.15(@babel/core@7.29.0(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4)
next-mdx-remote:
specifier: ^6.0.0
version: 6.0.0(@types/react@18.3.3)(react@18.3.1)(supports-color@8.1.1)
next-mdx-remote-client:
specifier: ^1.1.7
version: 1.1.7(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(unified@11.0.5)
next-seo:
specifier: ^6.5.0
version: 6.5.0(next@15.5.15(@babel/core@7.29.0(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -4501,6 +4501,9 @@ packages:
'@mdx-js/mdx@3.0.1':
resolution: {integrity: sha512-eIQ4QTrOWyL3LWEe/bu6Taqzq2HQvHcyTMaOrI95P2/LmJE7AsfPfgJGuFLPVqBUE1BC1rik3VIhU+s9u72arA==}
'@mdx-js/mdx@3.1.1':
resolution: {integrity: sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==}
'@mdx-js/react@3.1.1':
resolution: {integrity: sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==}
peerDependencies:
@@ -10716,6 +10719,12 @@ packages:
resolution: {integrity: sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==}
engines: {node: '>=0.12'}
esast-util-from-estree@2.0.0:
resolution: {integrity: sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==}
esast-util-from-js@2.0.1:
resolution: {integrity: sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==}
esbuild@0.25.2:
resolution: {integrity: sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==}
engines: {node: '>=18'}
@@ -10992,6 +11001,9 @@ packages:
estree-util-is-identifier-name@3.0.0:
resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==}
estree-util-scope@1.0.0:
resolution: {integrity: sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==}
estree-util-to-js@2.0.0:
resolution: {integrity: sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==}
@@ -13799,11 +13811,12 @@ packages:
react: '*'
react-dom: '*'
next-mdx-remote@6.0.0:
resolution: {integrity: sha512-cJEpEZlgD6xGjB4jL8BnI8FaYdN9BzZM4NwadPe1YQr7pqoWjg9EBCMv3nXBkuHqMRfv2y33SzUsuyNh9LFAQQ==}
engines: {node: '>=14', npm: '>=7'}
next-mdx-remote-client@1.1.7:
resolution: {integrity: sha512-12Ap5Z/tFIETMXFSBTH2IFEhJAso7MvOJ5ICyesA4q6FM4vtAcmb+4ZKa4tV1IVQJLBVqOhaEfIESZzdwjmrQQ==}
engines: {node: '>=20.9.0'}
peerDependencies:
react: '>=16'
react: '>= 18.3.0 < 19.0.0'
react-dom: '>= 18.3.0 < 19.0.0'
next-plugin-yaml@1.0.1:
resolution: {integrity: sha512-k13wbpN33wTgrgWUBiXPtObXO94JOEiwvYKJ3X0JrBz2yaW24EfNaVqHwA0dwhsn9PyPIKhPhgsu3bhJsNs+cQ==}
@@ -13964,6 +13977,10 @@ packages:
resolution: {integrity: sha512-2YEOR5qlI1zUFbGMLKNfsrR5JUvFg9LxIRVE+xJe962pfVLH0rnItqLzv96XVs1Y1UIR8FxsXAuvX/lYAWZ2BQ==}
engines: {node: '>=8'}
non-error@0.1.0:
resolution: {integrity: sha512-TMB1uHiGsHRGv1uYclfhivcnf0/PdFp2pNqRxXjncaAsjYMoisaQJI+SSZCqRq+VliwRTC8tsMQfmrWjDMhkPQ==}
engines: {node: '>=20'}
nopt@5.0.0:
resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==}
engines: {node: '>=6'}
@@ -15338,6 +15355,20 @@ packages:
resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==}
engines: {node: '>= 0.10'}
recma-build-jsx@1.0.0:
resolution: {integrity: sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==}
recma-jsx@1.0.1:
resolution: {integrity: sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==}
peerDependencies:
acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
recma-parse@1.0.0:
resolution: {integrity: sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==}
recma-stringify@1.0.0:
resolution: {integrity: sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==}
redent@3.0.0:
resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==}
engines: {node: '>=8'}
@@ -15408,6 +15439,9 @@ packages:
rehype-raw@7.0.0:
resolution: {integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==}
rehype-recma@1.0.0:
resolution: {integrity: sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==}
rehype-slug@5.1.0:
resolution: {integrity: sha512-Gf91dJoXneiorNEnn+Phx97CO7oRMrpi+6r155tTxzGuLtm+QrI4cTwCa9e1rtePdL4i9tSO58PeSS6HWfgsiw==}
@@ -15440,6 +15474,11 @@ packages:
remark-mdx-frontmatter@4.0.0:
resolution: {integrity: sha512-PZzAiDGOEfv1Ua7exQ8S5kKxkD8CDaSb4nM+1Mprs6u8dyvQifakh+kCj6NovfGXW+bTvrhjaR3srzjS2qJHKg==}
remark-mdx-remove-esm@1.3.1:
resolution: {integrity: sha512-POa8abdiuicD2e+zQkclxzJa5JEGLtV8XIOFVvisnGuw4l4xd6dfQozedwqR8JTeXQmxLebvYhlbwHoQP9RWkw==}
peerDependencies:
unified: ^11
remark-mdx@3.0.1:
resolution: {integrity: sha512-3Pz3yPQ5Rht2pM5R+0J2MrGoBSrzf+tJG94N+t/ilfdh8YLyyKYtidAYwTveB20BoHAcwIopOUqhcmh2F7hGYA==}
@@ -15746,6 +15785,10 @@ packages:
sentence-case@3.0.4:
resolution: {integrity: sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==}
serialize-error@13.0.1:
resolution: {integrity: sha512-bBZaRwLH9PN5HbLCjPId4dP5bNGEtumcErgOX952IsvOhVPrm3/AeK1y0UHA/QaPG701eg0yEnOKsCOC6X/kaA==}
engines: {node: '>=20'}
serialize-javascript@7.0.5:
resolution: {integrity: sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw==}
engines: {node: '>=20.0.0'}
@@ -20297,7 +20340,7 @@ snapshots:
'@mdx-js/esbuild@3.0.1(esbuild@0.25.2)(supports-color@8.1.1)':
dependencies:
'@mdx-js/mdx': 3.0.1(supports-color@8.1.1)
'@mdx-js/mdx': 3.1.1(supports-color@8.1.1)
'@types/unist': 3.0.3
esbuild: 0.25.2
vfile: 6.0.3
@@ -20342,6 +20385,36 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@mdx-js/mdx@3.1.1(supports-color@8.1.1)':
dependencies:
'@types/estree': 1.0.5
'@types/estree-jsx': 1.0.1
'@types/hast': 3.0.4
'@types/mdx': 2.0.10
acorn: 8.16.0
collapse-white-space: 2.1.0
devlop: 1.1.0
estree-util-is-identifier-name: 3.0.0
estree-util-scope: 1.0.0
estree-walker: 3.0.3
hast-util-to-jsx-runtime: 2.3.6(supports-color@8.1.1)
markdown-extensions: 2.0.0
recma-build-jsx: 1.0.0
recma-jsx: 1.0.1(acorn@8.16.0)
recma-stringify: 1.0.0
rehype-recma: 1.0.0(supports-color@8.1.1)
remark-mdx: 3.0.1(supports-color@8.1.1)
remark-parse: 11.0.0(supports-color@8.1.1)
remark-rehype: 11.1.1
source-map: 0.7.6
unified: 11.0.5
unist-util-position-from-estree: 2.0.0
unist-util-stringify-position: 4.0.0
unist-util-visit: 5.1.0
vfile: 6.0.3
transitivePeerDependencies:
- supports-color
'@mdx-js/react@3.1.1(@types/react@18.3.3)(react@18.3.1)':
dependencies:
'@types/mdx': 2.0.10
@@ -27357,6 +27430,20 @@ snapshots:
d: 1.0.2
ext: 1.7.0
esast-util-from-estree@2.0.0:
dependencies:
'@types/estree-jsx': 1.0.1
devlop: 1.1.0
estree-util-visit: 2.0.0
unist-util-position-from-estree: 2.0.0
esast-util-from-js@2.0.1:
dependencies:
'@types/estree-jsx': 1.0.1
acorn: 8.16.0
esast-util-from-estree: 2.0.0
vfile-message: 4.0.2
esbuild@0.25.2:
optionalDependencies:
'@esbuild/aix-ppc64': 0.25.2
@@ -27705,6 +27792,11 @@ snapshots:
estree-util-is-identifier-name@3.0.0: {}
estree-util-scope@1.0.0:
dependencies:
'@types/estree': 1.0.5
devlop: 1.1.0
estree-util-to-js@2.0.0:
dependencies:
'@types/estree-jsx': 1.0.1
@@ -31259,19 +31351,21 @@ snapshots:
- markdown-wasm
- supports-color
next-mdx-remote@6.0.0(@types/react@18.3.3)(react@18.3.1)(supports-color@8.1.1):
next-mdx-remote-client@1.1.7(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(unified@11.0.5):
dependencies:
'@babel/code-frame': 7.29.0
'@mdx-js/mdx': 3.0.1(supports-color@8.1.1)
'@mdx-js/mdx': 3.1.1(supports-color@8.1.1)
'@mdx-js/react': 3.1.1(@types/react@18.3.3)(react@18.3.1)
react: 18.3.1
unist-util-remove: 4.0.0
unist-util-visit: 5.1.0
react-dom: 18.3.1(react@18.3.1)
remark-mdx-remove-esm: 1.3.1(supports-color@8.1.1)(unified@11.0.5)
serialize-error: 13.0.1
vfile: 6.0.3
vfile-matter: 5.0.1
transitivePeerDependencies:
- '@types/react'
- supports-color
- unified
next-plugin-yaml@1.0.1:
dependencies:
@@ -31534,6 +31628,8 @@ snapshots:
dependencies:
big-integer: 1.6.51
non-error@0.1.0: {}
nopt@5.0.0:
dependencies:
abbrev: 1.1.1
@@ -33204,6 +33300,35 @@ snapshots:
dependencies:
resolve: 1.22.10
recma-build-jsx@1.0.0:
dependencies:
'@types/estree': 1.0.5
estree-util-build-jsx: 3.0.1
vfile: 6.0.3
recma-jsx@1.0.1(acorn@8.16.0):
dependencies:
acorn: 8.16.0
acorn-jsx: 5.3.2(acorn@8.16.0)
estree-util-to-js: 2.0.0
recma-parse: 1.0.0
recma-stringify: 1.0.0
unified: 11.0.5
recma-parse@1.0.0:
dependencies:
'@types/estree': 1.0.5
esast-util-from-js: 2.0.1
unified: 11.0.5
vfile: 6.0.3
recma-stringify@1.0.0:
dependencies:
'@types/estree': 1.0.5
estree-util-to-js: 2.0.0
unified: 11.0.5
vfile: 6.0.3
redent@3.0.0:
dependencies:
indent-string: 4.0.0
@@ -33324,6 +33449,14 @@ snapshots:
hast-util-raw: 9.0.1
vfile: 6.0.3
rehype-recma@1.0.0(supports-color@8.1.1):
dependencies:
'@types/estree': 1.0.5
'@types/hast': 3.0.4
hast-util-to-estree: 3.1.3(supports-color@8.1.1)
transitivePeerDependencies:
- supports-color
rehype-slug@5.1.0:
dependencies:
'@types/hast': 2.3.6
@@ -33406,6 +33539,15 @@ snapshots:
unified: 11.0.5
yaml: 2.8.3
remark-mdx-remove-esm@1.3.1(supports-color@8.1.1)(unified@11.0.5):
dependencies:
'@types/mdast': 4.0.4
mdast-util-mdxjs-esm: 2.0.1(supports-color@8.1.1)
unified: 11.0.5
unist-util-remove: 4.0.0
transitivePeerDependencies:
- supports-color
remark-mdx@3.0.1(supports-color@8.1.1):
dependencies:
mdast-util-mdx: 3.0.0(supports-color@8.1.1)
@@ -33805,6 +33947,11 @@ snapshots:
tslib: 2.8.1
upper-case-first: 2.0.2
serialize-error@13.0.1:
dependencies:
non-error: 0.1.0
type-fest: 5.4.4
serialize-javascript@7.0.5: {}
seroval-plugins@1.5.0(seroval@1.5.1):