Files
supabase/apps/design-system/lib/remark-jsx-components.ts
Francesco Sansalvadore e79f0d1dd1 feat(design-system): add Markdown component to ui-patterns (#46325)
## What kind of change does this PR introduce?

Add `Markdown` component 
- as a ui-pattern
- docs in design-system



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

* **New Features**
* Introduced a Markdown UI pattern with full documentation and a docs
sidebar entry.
* Markdown component supports composable renderers, optional lazy syntax
highlighting, and customizable element overrides.
* Added many interactive examples (full demo, headings, paragraphs,
lists, links, inline code, blockquotes, code blocks, tables, images,
horizontal rules) plus Quote and Avatar demos.
* **Documentation**
  * New MDX guide detailing usage, props, and customization previews.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46325?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-26 17:19:18 +02:00

34 lines
1.3 KiB
TypeScript

import { visit } from 'unist-util-visit'
// Matches self-closing JSX-like elements with PascalCase component names:
// <ComponentName />
// <ComponentName service="auth" />
const JSX_SELF_CLOSING = /^<([A-Z]\w*)((?:\s+[\w-]+(?:="[^"]*")?)*)\s*\/>$/
const ATTR_PATTERN = /([\w-]+)(?:="([^"]*)")?/g
/**
* Remark plugin that converts JSX-like self-closing tags (e.g. `<ErrorCodes service="auth" />`)
* in markdown into nodes that react-markdown maps to entries in the `components` prop —
* giving the ui-patterns `Markdown` component MDX-like behavior in design-system demos.
*/
export const remarkJsxComponents = () => (tree: any) => {
visit(tree, 'html', (node: any, index: number | undefined, parent: any) => {
if (!parent || index === undefined) return
const match = node.value.trim().match(JSX_SELF_CLOSING)
if (!match) return
const [, name, attrsStr] = match
const properties: Record<string, string | boolean> = {}
ATTR_PATTERN.lastIndex = 0
let attrMatch: RegExpExecArray | null
while ((attrMatch = ATTR_PATTERN.exec(attrsStr || '')) !== null) {
properties[attrMatch[1]] = attrMatch[2] !== undefined ? attrMatch[2] : true
}
parent.children[index] = {
type: 'jsxComponent',
data: { hName: name, hProperties: properties },
}
})
}