mirror of
https://github.com/supabase/supabase.git
synced 2026-10-09 11:25:06 +03:00
fix: Handle NavData component
This commit is contained in:
1 parent
8b3239fbb3
commit
4498f69bff
6 files changed
+335
-113
No files matched your search
@@ -1,14 +0,0 @@
|
||||
import { ReactNode } from 'react'
|
||||
|
||||
import { navDataForMdx } from './Navigation/NavigationMenu/NavigationMenu.constants'
|
||||
|
||||
export function NavData({
|
||||
data,
|
||||
children,
|
||||
}: {
|
||||
data: keyof typeof navDataForMdx
|
||||
children: (navItems: (typeof navDataForMdx)[keyof typeof navDataForMdx]) => ReactNode
|
||||
}) {
|
||||
const navItems = navDataForMdx[data]
|
||||
return children(navItems)
|
||||
}
|
||||
@@ -21,28 +21,145 @@ There are several reasons why you might want to add social login to your applica
|
||||
Supabase supports a suite of social providers. Follow these guides to configure a social provider for your platform.
|
||||
|
||||
<div className="grid grid-cols-12 xs:gap-x-10 gap-y-10 not-prose py-8">
|
||||
<NavData data="socialLoginItems">
|
||||
{(data) =>
|
||||
data.map((item) => (
|
||||
<Link
|
||||
href={`${item.url}`}
|
||||
key={item.name}
|
||||
passHref
|
||||
className="col-span-12 xs:col-span-6 lg:col-span-4 xl:col-span-3"
|
||||
>
|
||||
<IconPanel
|
||||
title={item.name}
|
||||
span="col-span-6"
|
||||
icon={item.icon}
|
||||
isDarkMode={item.isDarkMode}
|
||||
hasLightIcon={item.hasLightIcon}
|
||||
>
|
||||
{item.description}
|
||||
</IconPanel>
|
||||
</Link>
|
||||
))
|
||||
}
|
||||
</NavData>
|
||||
<Link
|
||||
href="/guides/auth/social-login/auth-google"
|
||||
passHref
|
||||
className="col-span-12 xs:col-span-6 lg:col-span-4 xl:col-span-3"
|
||||
>
|
||||
<IconPanel title="Google" span="col-span-6" icon="/docs/img/icons/google-icon" />
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/auth/social-login/auth-facebook"
|
||||
passHref
|
||||
className="col-span-12 xs:col-span-6 lg:col-span-4 xl:col-span-3"
|
||||
>
|
||||
<IconPanel title="Facebook" span="col-span-6" icon="/docs/img/icons/facebook-icon" />
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/auth/social-login/auth-apple"
|
||||
passHref
|
||||
className="col-span-12 xs:col-span-6 lg:col-span-4 xl:col-span-3"
|
||||
>
|
||||
<IconPanel title="Apple" span="col-span-6" icon="/docs/img/icons/apple-icon" />
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/auth/social-login/auth-azure"
|
||||
passHref
|
||||
className="col-span-12 xs:col-span-6 lg:col-span-4 xl:col-span-3"
|
||||
>
|
||||
<IconPanel title="Azure (Microsoft)" span="col-span-6" icon="/docs/img/icons/microsoft-icon" />
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/auth/social-login/auth-twitter"
|
||||
passHref
|
||||
className="col-span-12 xs:col-span-6 lg:col-span-4 xl:col-span-3"
|
||||
>
|
||||
<IconPanel title="Twitter" span="col-span-6" icon="/docs/img/icons/twitter-icon" hasLightIcon />
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/auth/social-login/auth-github"
|
||||
passHref
|
||||
className="col-span-12 xs:col-span-6 lg:col-span-4 xl:col-span-3"
|
||||
>
|
||||
<IconPanel
|
||||
title="GitHub"
|
||||
span="col-span-6"
|
||||
icon="/docs/img/icons/github-icon"
|
||||
isDarkMode
|
||||
hasLightIcon
|
||||
/>
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/auth/social-login/auth-gitlab"
|
||||
passHref
|
||||
className="col-span-12 xs:col-span-6 lg:col-span-4 xl:col-span-3"
|
||||
>
|
||||
<IconPanel title="Gitlab" span="col-span-6" icon="/docs/img/icons/gitlab-icon" />
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/auth/social-login/auth-bitbucket"
|
||||
passHref
|
||||
className="col-span-12 xs:col-span-6 lg:col-span-4 xl:col-span-3"
|
||||
>
|
||||
<IconPanel title="Bitbucket" span="col-span-6" icon="/docs/img/icons/bitbucket-icon" />
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/auth/social-login/auth-discord"
|
||||
passHref
|
||||
className="col-span-12 xs:col-span-6 lg:col-span-4 xl:col-span-3"
|
||||
>
|
||||
<IconPanel title="Discord" span="col-span-6" icon="/docs/img/icons/discord-icon" />
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/auth/social-login/auth-figma"
|
||||
passHref
|
||||
className="col-span-12 xs:col-span-6 lg:col-span-4 xl:col-span-3"
|
||||
>
|
||||
<IconPanel title="Figma" span="col-span-6" icon="/docs/img/icons/figma-icon" />
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/auth/social-login/auth-kakao"
|
||||
passHref
|
||||
className="col-span-12 xs:col-span-6 lg:col-span-4 xl:col-span-3"
|
||||
>
|
||||
<IconPanel title="Kakao" span="col-span-6" icon="/docs/img/icons/kakao-icon" />
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/auth/social-login/auth-keycloak"
|
||||
passHref
|
||||
className="col-span-12 xs:col-span-6 lg:col-span-4 xl:col-span-3"
|
||||
>
|
||||
<IconPanel title="Keycloak" span="col-span-6" icon="/docs/img/icons/keycloak-icon" />
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/auth/social-login/auth-linkedin"
|
||||
passHref
|
||||
className="col-span-12 xs:col-span-6 lg:col-span-4 xl:col-span-3"
|
||||
>
|
||||
<IconPanel title="LinkedIn" span="col-span-6" icon="/docs/img/icons/linkedin-icon" />
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/auth/social-login/auth-notion"
|
||||
passHref
|
||||
className="col-span-12 xs:col-span-6 lg:col-span-4 xl:col-span-3"
|
||||
>
|
||||
<IconPanel title="Notion" span="col-span-6" icon="/docs/img/icons/notion-icon" />
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/auth/social-login/auth-slack"
|
||||
passHref
|
||||
className="col-span-12 xs:col-span-6 lg:col-span-4 xl:col-span-3"
|
||||
>
|
||||
<IconPanel title="Slack" span="col-span-6" icon="/docs/img/icons/slack-icon" />
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/auth/social-login/auth-spotify"
|
||||
passHref
|
||||
className="col-span-12 xs:col-span-6 lg:col-span-4 xl:col-span-3"
|
||||
>
|
||||
<IconPanel title="Spotify" span="col-span-6" icon="/docs/img/icons/spotify-icon" />
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/auth/social-login/auth-twitch"
|
||||
passHref
|
||||
className="col-span-12 xs:col-span-6 lg:col-span-4 xl:col-span-3"
|
||||
>
|
||||
<IconPanel title="Twitch" span="col-span-6" icon="/docs/img/icons/twitch-icon" />
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/auth/social-login/auth-workos"
|
||||
passHref
|
||||
className="col-span-12 xs:col-span-6 lg:col-span-4 xl:col-span-3"
|
||||
>
|
||||
<IconPanel title="WorkOS" span="col-span-6" icon="/docs/img/icons/workos-icon" />
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/auth/social-login/auth-zoom"
|
||||
passHref
|
||||
className="col-span-12 xs:col-span-6 lg:col-span-4 xl:col-span-3"
|
||||
>
|
||||
<IconPanel title="Zoom" span="col-span-6" icon="/docs/img/icons/zoom-icon" />
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<Admonition type="tip">
|
||||
|
||||
@@ -32,32 +32,54 @@ The IPv4 add-on is not dual-stack: enabling it swaps the project's IPv6 (AAAA) D
|
||||
## Quickstarts
|
||||
|
||||
<div className="grid grid-cols-[repeat(auto-fit,minmax(150px,1fr))] gap-6 not-prose">
|
||||
<NavData data="ormQuickstarts">
|
||||
{(data) =>
|
||||
data.items?.map((quickstart) => (
|
||||
<Link key={quickstart.url} href={quickstart.url} passHref>
|
||||
<GlassPanel
|
||||
key={quickstart.name}
|
||||
title={quickstart.name}
|
||||
className="[&>div]:p-2 flex justify-center [&_p]:text-foreground-light"
|
||||
/>
|
||||
</Link>
|
||||
))
|
||||
}
|
||||
</NavData>
|
||||
<NavData data="guiQuickstarts">
|
||||
{(data) =>
|
||||
data.items?.map((quickstart) => (
|
||||
<Link key={quickstart.url} href={quickstart.url} passHref>
|
||||
<GlassPanel
|
||||
key={quickstart.name}
|
||||
title={quickstart.name}
|
||||
className="[&>div]:p-2 flex justify-center [&_p]:text-foreground-light"
|
||||
/>
|
||||
</Link>
|
||||
))
|
||||
}
|
||||
</NavData>
|
||||
<Link href="/guides/database/prisma" passHref>
|
||||
<GlassPanel
|
||||
title="Prisma"
|
||||
className="[&>div]:p-2 flex justify-center [&_p]:text-foreground-light"
|
||||
/>
|
||||
</Link>
|
||||
<Link href="/guides/database/drizzle" passHref>
|
||||
<GlassPanel
|
||||
title="Drizzle"
|
||||
className="[&>div]:p-2 flex justify-center [&_p]:text-foreground-light"
|
||||
/>
|
||||
</Link>
|
||||
<Link href="/guides/database/postgres-js" passHref>
|
||||
<GlassPanel
|
||||
title="Postgres.js"
|
||||
className="[&>div]:p-2 flex justify-center [&_p]:text-foreground-light"
|
||||
/>
|
||||
</Link>
|
||||
<Link href="/guides/database/pgadmin" passHref>
|
||||
<GlassPanel
|
||||
title="pgAdmin"
|
||||
className="[&>div]:p-2 flex justify-center [&_p]:text-foreground-light"
|
||||
/>
|
||||
</Link>
|
||||
<Link href="/guides/database/psql" passHref>
|
||||
<GlassPanel
|
||||
title="PSQL"
|
||||
className="[&>div]:p-2 flex justify-center [&_p]:text-foreground-light"
|
||||
/>
|
||||
</Link>
|
||||
<Link href="/guides/database/dbeaver" passHref>
|
||||
<GlassPanel
|
||||
title="DBeaver"
|
||||
className="[&>div]:p-2 flex justify-center [&_p]:text-foreground-light"
|
||||
/>
|
||||
</Link>
|
||||
<Link href="/guides/database/metabase" passHref>
|
||||
<GlassPanel
|
||||
title="Metabase"
|
||||
className="[&>div]:p-2 flex justify-center [&_p]:text-foreground-light"
|
||||
/>
|
||||
</Link>
|
||||
<Link href="/guides/database/beekeeper-studio" passHref>
|
||||
<GlassPanel
|
||||
title="Beekeeper Studio"
|
||||
className="[&>div]:p-2 flex justify-center [&_p]:text-foreground-light"
|
||||
/>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
## Data APIs and client libraries
|
||||
|
||||
@@ -6,20 +6,104 @@ Learn how to migrate to Supabase from another database service.
|
||||
|
||||
## Migration guides
|
||||
|
||||
<NavData data="migrationPages">
|
||||
{(migrationPages) => (
|
||||
<div className="grid grid-cols-[repeat(auto-fit,minmax(200px,1fr))] gap-6 mb-6 not-prose">
|
||||
{migrationPages.map((page) => (
|
||||
<Link href={`${page.url}`} key={page.url} passHref>
|
||||
<GlassPanel
|
||||
icon={page.icon}
|
||||
title={page.name}
|
||||
hasLightIcon={page.hasLightIcon}
|
||||
background={false}
|
||||
className="[&>div]:p-4"
|
||||
/>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</NavData>
|
||||
<div className="grid grid-cols-[repeat(auto-fit,minmax(200px,1fr))] gap-6 mb-6 not-prose">
|
||||
<Link href="/guides/platform/migrating-to-supabase/auth0" passHref>
|
||||
<GlassPanel
|
||||
icon="/docs/img/icons/auth0-icon"
|
||||
title="Auth0"
|
||||
hasLightIcon
|
||||
background={false}
|
||||
className="[&>div]:p-4"
|
||||
/>
|
||||
</Link>
|
||||
<Link href="/guides/platform/migrating-to-supabase/firebase-auth" passHref>
|
||||
<GlassPanel
|
||||
icon="/docs/img/icons/firebase-icon"
|
||||
title="Firebase Auth"
|
||||
background={false}
|
||||
className="[&>div]:p-4"
|
||||
/>
|
||||
</Link>
|
||||
<Link href="/guides/platform/migrating-to-supabase/firestore-data" passHref>
|
||||
<GlassPanel
|
||||
icon="/docs/img/icons/firebase-icon"
|
||||
title="Firestore Data"
|
||||
background={false}
|
||||
className="[&>div]:p-4"
|
||||
/>
|
||||
</Link>
|
||||
<Link href="/guides/platform/migrating-to-supabase/firebase-storage" passHref>
|
||||
<GlassPanel
|
||||
icon="/docs/img/icons/firebase-icon"
|
||||
title="Firebase Storage"
|
||||
background={false}
|
||||
className="[&>div]:p-4"
|
||||
/>
|
||||
</Link>
|
||||
<Link href="/guides/platform/migrating-to-supabase/heroku" passHref>
|
||||
<GlassPanel
|
||||
icon="/docs/img/icons/heroku-icon"
|
||||
title="Heroku"
|
||||
background={false}
|
||||
className="[&>div]:p-4"
|
||||
/>
|
||||
</Link>
|
||||
<Link href="/guides/platform/migrating-to-supabase/render" passHref>
|
||||
<GlassPanel
|
||||
icon="/docs/img/icons/render-icon"
|
||||
title="Render"
|
||||
background={false}
|
||||
className="[&>div]:p-4"
|
||||
/>
|
||||
</Link>
|
||||
<Link href="/guides/platform/migrating-to-supabase/amazon-rds" passHref>
|
||||
<GlassPanel
|
||||
icon="/docs/img/icons/aws-rds-icon"
|
||||
title="Amazon RDS"
|
||||
background={false}
|
||||
className="[&>div]:p-4"
|
||||
/>
|
||||
</Link>
|
||||
<Link href="/guides/platform/migrating-to-supabase/postgres" passHref>
|
||||
<GlassPanel
|
||||
icon="/docs/img/icons/postgres-icon"
|
||||
title="Postgres"
|
||||
background={false}
|
||||
className="[&>div]:p-4"
|
||||
/>
|
||||
</Link>
|
||||
<Link href="/guides/platform/migrating-to-supabase/vercel-postgres" passHref>
|
||||
<GlassPanel
|
||||
icon="/docs/img/icons/vercel-icon"
|
||||
title="Vercel Postgres"
|
||||
hasLightIcon
|
||||
background={false}
|
||||
className="[&>div]:p-4"
|
||||
/>
|
||||
</Link>
|
||||
<Link href="/guides/platform/migrating-to-supabase/neon" passHref>
|
||||
<GlassPanel
|
||||
icon="/docs/img/icons/neon-icon"
|
||||
title="Neon"
|
||||
hasLightIcon
|
||||
background={false}
|
||||
className="[&>div]:p-4"
|
||||
/>
|
||||
</Link>
|
||||
<Link href="/guides/platform/migrating-to-supabase/mysql" passHref>
|
||||
<GlassPanel
|
||||
icon="/docs/img/icons/mysql-icon"
|
||||
title="MySQL"
|
||||
background={false}
|
||||
className="[&>div]:p-4"
|
||||
/>
|
||||
</Link>
|
||||
<Link href="/guides/platform/migrating-to-supabase/mssql" passHref>
|
||||
<GlassPanel
|
||||
icon="/docs/img/icons/mssql-icon"
|
||||
title="MSSQL"
|
||||
background={false}
|
||||
className="[&>div]:p-4"
|
||||
/>
|
||||
</Link>
|
||||
</div>
|
||||
@@ -10,7 +10,6 @@ import { Extensions } from '~/components/Extensions'
|
||||
import Image, { type ImageProps } from '~/components/Image'
|
||||
import { Mermaid } from '~/components/Mermaid'
|
||||
import { MetricsStackCards } from '~/components/MetricsStackCards'
|
||||
import { NavData } from '~/components/NavData'
|
||||
import { Price } from '~/components/Price'
|
||||
import { ProjectConfigVariables } from '~/components/ProjectConfigVariables'
|
||||
import { RealtimeLimitsEstimator } from '~/components/RealtimeLimitsEstimator'
|
||||
@@ -89,7 +88,6 @@ const components = {
|
||||
Mermaid,
|
||||
MetricsStackCards,
|
||||
NamedCodeBlock,
|
||||
NavData,
|
||||
ProjectConfigVariables,
|
||||
RealtimeLimitsEstimator,
|
||||
RegionsList,
|
||||
|
||||
@@ -245,40 +245,55 @@ function convertLinkPanels(content: string): string {
|
||||
if (!hrefMatch) return full
|
||||
const href = withDocsBasePath(hrefMatch[1])
|
||||
|
||||
const panelOpen = body.match(/<(GlassPanel|IconPanel)\b/)
|
||||
if (!panelOpen) return full
|
||||
const panelName = panelOpen[1]
|
||||
const panelStart = panelOpen.index ?? 0
|
||||
const panelOpen = body.match(/<(GlassPanel|IconPanel)\b/)
|
||||
if (!panelOpen) return full
|
||||
const panelName = panelOpen[1]
|
||||
const panelStart = panelOpen.index ?? 0
|
||||
|
||||
// Walk past the opening tag, respecting JSX expression braces so attribute
|
||||
// values like `title={<span>...</span>}` don't terminate parsing early.
|
||||
let i = panelStart + panelOpen[0].length
|
||||
let depth = 0
|
||||
while (i < body.length) {
|
||||
const ch = body[i]
|
||||
if (ch === '{') depth++
|
||||
else if (ch === '}') depth--
|
||||
else if (ch === '>' && depth === 0) break
|
||||
i++
|
||||
// Walk past the opening tag, respecting both JSX `{}` expression depth
|
||||
// (so `title={<span>...</span>}` doesn't terminate early) and quoted
|
||||
// attribute values (so `>` inside `className="[&>div]..."` is ignored).
|
||||
let i = panelStart + panelOpen[0].length
|
||||
let depth = 0
|
||||
let quote: string | null = null
|
||||
while (i < body.length) {
|
||||
const ch = body[i]
|
||||
if (quote) {
|
||||
if (ch === quote) quote = null
|
||||
} else if (ch === '"' || ch === "'") {
|
||||
quote = ch
|
||||
} else if (ch === '{') {
|
||||
depth++
|
||||
} else if (ch === '}') {
|
||||
depth--
|
||||
} else if (ch === '>' && depth === 0) {
|
||||
break
|
||||
}
|
||||
i++
|
||||
}
|
||||
if (i >= body.length) return full
|
||||
|
||||
const panelAttrs = body.slice(panelStart + panelOpen[0].length, i)
|
||||
const title = extractTitleAttr(panelAttrs)
|
||||
if (!title) return full
|
||||
|
||||
// Self-closing panels (`<GlassPanel ... />`) carry no description.
|
||||
const isSelfClosing = panelAttrs.trimEnd().endsWith('/')
|
||||
let description = ''
|
||||
if (!isSelfClosing) {
|
||||
const closingTag = `</${panelName}>`
|
||||
const closeIdx = body.indexOf(closingTag, i)
|
||||
if (closeIdx === -1) return full
|
||||
description = body
|
||||
.slice(i + 1, closeIdx)
|
||||
.replace(/<[^>]+>/g, ' ')
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim()
|
||||
}
|
||||
|
||||
return `- [${title}](${href})${description ? `. ${description}` : ''}`
|
||||
}
|
||||
if (i >= body.length) return full
|
||||
|
||||
const panelAttrs = body.slice(panelStart + panelOpen[0].length, i)
|
||||
const closingTag = `</${panelName}>`
|
||||
const closeIdx = body.indexOf(closingTag, i)
|
||||
if (closeIdx === -1) return full
|
||||
|
||||
const title = extractTitleAttr(panelAttrs)
|
||||
if (!title) return full
|
||||
|
||||
const description = body
|
||||
.slice(i + 1, closeIdx)
|
||||
.replace(/<[^>]+>/g, ' ')
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim()
|
||||
|
||||
return `- [${title}](${href})${description ? `. ${description}` : ''}`
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user