Markdown
Markdown renders content written in Markdown (articles, release notes, CMS fields) with Prose typography, safely for untrusted content.
javascript: or data: links keep only their label. Relative links (/path, #id) are kept; external links open in a new tab. inline is for one-line text: inline Markdown only, in a <span>. renderLink hands links to the app's router. For text that arrives token by token (AI answers), use StreamingMarkdown.Getting started with the API
Every request needs an API key in the Authorization header. Create one under Settings.
- Create a read-only key.
- Store the key in an environment variable.
- Try
GET /v1/orders.
| Plan | Requests / min |
|---|---|
| Free | 60 |
| Pro | 1,200 |
Import
Install from npm, copy the source into your project with @yugen-ui/cli or the shadcn CLI, or import directly when working in this repo.
// npm install yugen-uiimport { Markdown } from "yugen-ui";Variants
Each tile is a standalone example: hover to copy, or press Code to see the source.
- Call
sonner.promiseto turn loading into the result. - HTML from a CMS? See Prose.
Inline
inline renders inline Markdown in a <span>, without a <p>: for list items, table cells, one-line descriptions.
Read the installation guide or Prose. Source code is on GitHub.
Path: /
Links through a router
renderLink gets href, title, the label and external; internal links go through the app's router (router.navigate, the router's <Link to>) instead of reloading the page. The example stands in state for the router.
<img src=x onerror="alert(1)"> and click here
Untrusted content
HTML shows as text and a javascript: link keeps only its label; no need to sanitize first.
Usage
- Use Markdown for written or CMS content; use StreamingMarkdown for text that arrives token by token.
- Use inline for one-line text inside another layout (list items, table cells).
- Turn on headingIds when the page has a table of contents or links to headings.
- Don't use Markdown to show HTML from a CMS: the HTML shows as text. Use Prose with sanitized HTML.
- Don't put Markdown inside Prose: Markdown already wraps itself in Prose.
Props
| Prop · Type | Default | Description |
|---|---|---|
| childrenstring | Default: — | Markdown content. No HTML. |
| inlineboolean | Default: false | Inline Markdown only (bold, italic, strikethrough, code, links) in a <span>, without paragraphs. |
| size"medium" | "large" | Default: "medium" | Prose text size: body1 (14px) or body2 (16px). |
| headingOffsetnumber | Default: 1 | Added to heading levels: by default # renders as h2. |
| headingIdsboolean | ((text: string) => string) | Default: false | Gives headings an id from their text (accents removed, -2, -3 for duplicates); pass a function to make your own ids. |
| breaksboolean | Default: false | Single newlines become <br>. |
| renderLink(link: MarkdownLink) => ReactNode | Default: — | Renders every link yourself; MarkdownLink has href, title, children and external. |
Messages
Text built into the component: labels, aria-labels, screen reader announcements.
English by default. Change it with the messages prop of YugenProvider, by the namespace below; messagesVi has the Vietnamese set. See Interface language.
messages.markdown
| Key · Type | Default (English) | messagesVi |
|---|---|---|
| newTabstring Chữ ẩn sau link mở tab mới. | Default (English)"(opens in new tab)" | messagesVi"(mở tab mới)" |
| taskDonestring Chữ ẩn trước mục danh sách việc đã xong / chưa xong. | Default (English)"Done:" | messagesVi"Đã xong:" |
| taskTodostring | Default (English)"Not done:" | messagesVi"Chưa xong:" |
| tablestring Tên vùng cuộn của bảng. | Default (English)"Table" | messagesVi"Bảng" |