mirror of
https://github.com/supabase/supabase.git
synced 2026-05-10 02:39:56 -04:00
743d665dfe
## 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 -->
82 lines
2.5 KiB
TypeScript
82 lines
2.5 KiB
TypeScript
import { remarkCodeHike, type CodeHikeConfig } from '@code-hike/mdx'
|
|
import codeHikeTheme from 'config/code-hike.theme.json' with { type: 'json' }
|
|
import type { SerializeOptions } from 'next-mdx-remote-client/serialize'
|
|
import rehypeSlug from 'rehype-slug'
|
|
import remarkGfm from 'remark-gfm'
|
|
|
|
const codeHikeOptions: CodeHikeConfig = {
|
|
theme: codeHikeTheme,
|
|
lineNumbers: true,
|
|
showCopyButton: true,
|
|
skipLanguages: ['mermaid'],
|
|
autoImport: false,
|
|
}
|
|
|
|
type MdxOptions = NonNullable<SerializeOptions['mdxOptions']>
|
|
|
|
export const mdxOptionsBlog: MdxOptions = {
|
|
remarkPlugins: [remarkNormalizeHtmlImages, [remarkCodeHike, codeHikeOptions], remarkGfm],
|
|
rehypePlugins: [
|
|
// @ts-ignore
|
|
rehypeSlug,
|
|
],
|
|
}
|
|
|
|
/**
|
|
* Remark plugin: converts raw HTML `<img>` nodes and MDX JSX `<img />` elements
|
|
* to standard markdown `image` AST nodes so they go through the mdxComponents
|
|
* img rendering pipeline.
|
|
*/
|
|
function remarkNormalizeHtmlImages() {
|
|
return function transformer(tree: any) {
|
|
const getAttrFromString = (attrs: string, name: string) => {
|
|
const m = attrs.match(new RegExp(`${name}\\s*=\\s*("([^"]*)"|'([^']*)')`, 'i'))
|
|
return (m?.[2] ?? m?.[3] ?? '').trim()
|
|
}
|
|
|
|
const walk = (node: any, parent: any, index: number) => {
|
|
if (node.type === 'code' || node.type === 'inlineCode') return
|
|
|
|
if (parent !== null) {
|
|
if (node.type === 'html') {
|
|
const match = /^\s*<img\b([^>]*)\/?>\s*$/i.exec(node.value)
|
|
if (match) {
|
|
const src = getAttrFromString(match[1], 'src')
|
|
if (src) {
|
|
const alt = getAttrFromString(match[1], 'alt')
|
|
parent.children[index] = { type: 'image', url: src, alt, title: null }
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
if (
|
|
(node.type === 'mdxJsxFlowElement' || node.type === 'mdxJsxTextElement') &&
|
|
node.name === 'img'
|
|
) {
|
|
const getJsxAttr = (name: string): string => {
|
|
const attr = node.attributes?.find(
|
|
(a: any) => a.type === 'mdxJsxAttribute' && a.name === name
|
|
)
|
|
return typeof attr?.value === 'string' ? attr.value : ''
|
|
}
|
|
const src = getJsxAttr('src')
|
|
if (src) {
|
|
const alt = getJsxAttr('alt')
|
|
parent.children[index] = { type: 'image', url: src, alt, title: null }
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
if (node.children) {
|
|
for (let i = 0; i < node.children.length; i++) {
|
|
walk(node.children[i], node, i)
|
|
}
|
|
}
|
|
}
|
|
|
|
walk(tree, null, 0)
|
|
}
|
|
}
|