mirror of
https://github.com/supabase/supabase.git
synced 2026-10-19 16:19:10 +03:00
## Problem design-system, ui-library and learn highlight code through `@shikijs/compat` and `rehype-pretty-code` 0.9, which both predate shiki 1 compat has no v4 release, so these apps were stuck on shiki 1.6 and couldn't pick up the injection fix from the previous pr ## Solution - drops `@shikijs/compat` - moves all three apps to `rehype-pretty-code` <!-- ## Preview links If relevant, include links to changed pages for easy review access. Copy the preview base URL from the Vercel bot comment on this PR. Use the following table as an example template. | Site | Live | Preview | Search for | | -------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | ----------------------------- | | WWW | [/blog/your-post](https://supabase.com/blog/your-post) | [/blog/your-post](https://zone-www-dot-com-git-branch-name-supabase.vercel.app/blog/your-post) | unique phrase from the change | | Docs | [/docs/guides/your-page](https://supabase.com/docs/guides/your-page) | [/docs/guides/your-page](https://docs-git-branch-name-supabase.vercel.app/docs/guides/your-page) | unique phrase from the change | | Studio | [/dashboard](https://supabase.com/dashboard) | [/dashboard](https://studio-git-branch-name-supabase.vercel.app/dashboard) | unique phrase from the change | | Design system | [/design-system](https://supabase.com/design-system) | [/design-system](https://design-system-git-branch-name-supabase.vercel.app/design-system) | unique phrase from the change | | UI library | [/library](https://supabase.com/library) | [/library](https://ui-library-git-branch-name-supabase.vercel.app/library) | unique phrase from the change | | Knowledge base | [/kb/guides/your-page](https://supabase.com/kb/guides/your-page) | [/kb/guides/your-page](https://kb-git-branch-name-supabase.vercel.app/kb/guides/your-page) | unique phrase from the change | --> <!-- ## Additional context Optionally add any other context or screenshots. --> ## Review instructions 1. open [/design-system/docs/accessibility](https://design-system-gd7xzujta-supabase.vercel.app/design-system/docs/accessibility) on the preview and on production side by side _ highlighted lines should keep the left border and background, and line numbers should line up 2. open [/design-system/docs/components/chart](https://design-system-gd7xzujta-supabase.vercel.app/design-system/docs/components/chart) _ highlighted words should have the gray pill, with no yellow background or black text + code blocks with titles should still show the title above the block 3. toggle light and dark mode on both pages _ token colors and the block background should match production 4. open [ui-library preview](https://ui-library-hmuv1teie-supabase.vercel.app/library/docs/starters/nextjs-starter) and do a copy check 5. open a learn lesson with code `/foundations/authentication` and compare it with production. ## Checklist Check all before review: - [x] I have read [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) - [x] If I wrote a new docs topic or edited an existing topic, I used the `/write-the-docs` or `/edit-the-docs` skill, which applies the docs [style guide](https://github.com/supabase/supabase/tree/master/apps/docs/style-guide)
170 lines
5.4 KiB
JavaScript
170 lines
5.4 KiB
JavaScript
import { readFile } from 'node:fs/promises'
|
|
import path from 'path'
|
|
import rehypeAutolinkHeadings from 'rehype-autolink-headings'
|
|
import rehypePrettyCode from 'rehype-pretty-code'
|
|
import rehypeSlug from 'rehype-slug'
|
|
import { codeImport } from 'remark-code-import'
|
|
import remarkGfm from 'remark-gfm'
|
|
import { visit } from 'unist-util-visit'
|
|
import { defineConfig, s } from 'velite'
|
|
|
|
const codeTheme = JSON.parse(
|
|
await readFile(path.join(process.cwd(), 'lib/themes/supabase-2.json'), 'utf8')
|
|
)
|
|
|
|
const LinksProperties = s.object({
|
|
doc: s.string().optional(),
|
|
api: s.string().optional(),
|
|
})
|
|
|
|
const NestedProperties = s.object({
|
|
radix: s.boolean().optional(),
|
|
shadcn: s.boolean().optional(),
|
|
vaul: s.boolean().optional(),
|
|
inputOtp: s.boolean().optional(),
|
|
reactAccessibleTreeview: s.boolean().optional(),
|
|
})
|
|
|
|
// The MDX is the only reliable source for which registry item v0 can open: doc
|
|
// slugs don't map onto registry names, and pages that install a client first
|
|
// list it as an extra BlockItem that opts out. Take the first item still opted in.
|
|
const getV0RegistryName = (raw) => {
|
|
for (const [, attributes] of raw.matchAll(/<BlockItem\b([^>]*?)\/?>/g)) {
|
|
if (/showOpenInV0=\{false\}/.test(attributes)) continue
|
|
const name = attributes.match(/name="([^"]+)"/)
|
|
if (name) return name[1]
|
|
}
|
|
return undefined
|
|
}
|
|
|
|
const docs = s
|
|
.object({
|
|
title: s.string(),
|
|
description: s.string(),
|
|
preview: s.mdx({ copyLinkedFiles: false }).optional(),
|
|
published: s.boolean().default(true),
|
|
links: LinksProperties.optional(),
|
|
featured: s.boolean().default(false),
|
|
component: s.boolean().default(false),
|
|
fragment: s.boolean().default(false),
|
|
source: NestedProperties.optional(),
|
|
// mirrors contentlayer2's `_raw.flattenedPath`: file path relative to the
|
|
// content dir, extension stripped, trailing `/index` dropped.
|
|
path: s.path(),
|
|
raw: s.raw(),
|
|
// internal doc cross-links (e.g. `[Button](components/button)`) aren't
|
|
// real files on disk — disable Velite's default asset-copying behavior,
|
|
// which otherwise treats every relative link as a local file to copy.
|
|
code: s.mdx({ copyLinkedFiles: false }),
|
|
})
|
|
.transform(({ path: flattenedPath, ...data }) => ({
|
|
...data,
|
|
slug: `/${flattenedPath}`,
|
|
slugAsParams: flattenedPath.split('/').slice(1).join('/'),
|
|
v0Name: getV0RegistryName(data.raw),
|
|
}))
|
|
|
|
export default defineConfig({
|
|
root: './content',
|
|
output: {
|
|
clean: true,
|
|
},
|
|
collections: {
|
|
allDocs: {
|
|
name: 'Doc',
|
|
pattern: 'docs/**/*.mdx',
|
|
schema: docs,
|
|
},
|
|
},
|
|
mdx: {
|
|
remarkPlugins: [remarkGfm, codeImport],
|
|
rehypePlugins: [
|
|
rehypeSlug,
|
|
() => (tree) => {
|
|
visit(tree, (node) => {
|
|
if (node?.type === 'element' && node?.tagName === 'pre') {
|
|
const [codeEl] = node.children
|
|
if (codeEl.tagName !== 'code') {
|
|
return
|
|
}
|
|
|
|
if (codeEl.data?.meta) {
|
|
// Extract event from meta and pass it down the tree.
|
|
const regex = /event="([^"]*)"/
|
|
const match = codeEl.data?.meta.match(regex)
|
|
if (match) {
|
|
node.__event__ = match ? match[1] : null
|
|
codeEl.data.meta = codeEl.data.meta.replace(regex, '')
|
|
}
|
|
}
|
|
|
|
node.__rawString__ = codeEl.children?.[0].value
|
|
node.__src__ = node.properties?.__src__
|
|
node.__style__ = node.properties?.__style__
|
|
}
|
|
})
|
|
},
|
|
[
|
|
rehypePrettyCode,
|
|
{
|
|
// plugin shares one cached highlighter per theme, lazy language loading needs shiki >= 4.5 (shikijs/shiki#1318)
|
|
theme: codeTheme,
|
|
keepBackground: false,
|
|
onVisitLine(node) {
|
|
// Prevent lines from collapsing in `display: grid` mode, and allow empty
|
|
// lines to be copy/pasted
|
|
if (node.children.length === 0) {
|
|
node.children = [{ type: 'text', value: ' ' }]
|
|
}
|
|
},
|
|
onVisitHighlightedLine(node) {
|
|
// the plugin strips the `line` class first, leaving className undefined
|
|
node.properties.className = [...(node.properties.className ?? []), 'line--highlighted']
|
|
},
|
|
onVisitHighlightedChars(node) {
|
|
node.properties.className = ['word--highlighted']
|
|
},
|
|
},
|
|
],
|
|
() => (tree) => {
|
|
visit(tree, (node) => {
|
|
if (node?.type === 'element' && node?.tagName === 'figure') {
|
|
if (!('data-rehype-pretty-code-figure' in node.properties)) {
|
|
return
|
|
}
|
|
|
|
const preElement = node.children.at(-1)
|
|
if (preElement.tagName !== 'pre') {
|
|
return
|
|
}
|
|
|
|
preElement.properties['__withMeta__'] = node.children.at(0).tagName === 'figcaption'
|
|
preElement.properties['__rawString__'] = node.__rawString__
|
|
|
|
if (node.__src__) {
|
|
preElement.properties['__src__'] = node.__src__
|
|
}
|
|
|
|
if (node.__event__) {
|
|
preElement.properties['__event__'] = node.__event__
|
|
}
|
|
|
|
if (node.__style__) {
|
|
preElement.properties['__style__'] = node.__style__
|
|
}
|
|
}
|
|
})
|
|
},
|
|
[
|
|
rehypeAutolinkHeadings,
|
|
{
|
|
properties: {
|
|
className: ['subheading-anchor'],
|
|
ariaLabel: 'Link to section',
|
|
},
|
|
},
|
|
],
|
|
],
|
|
},
|
|
})
|