# Markdown Viewer

Markdown rendering with tables, task lists, alerts, highlighted code, and sanitized HTML.

Page: https://sui.draco.dev/docs/components/markdown-viewer

### Example: markdown-viewer-demo

````tsx
"use client";
import { MarkdownViewer } from "@workspace/ui/components/markdown-viewer";
import type { ExampleProps } from "../types";
export default function Example({ locale }: ExampleProps) {
  const chinese = locale === "zh-CN";
  const content = chinese
    ? '# 发布说明\n\n支持 **Markdown**、表格和任务列表。\n\n> [!TIP]\n> 使用语义颜色构建一致的界面。\n\n| 组件 | 状态 |\n| --- | --- |\n| Editor | 就绪 |\n| Markdown Viewer | 就绪 |\n\n- [x] 双语文档\n- [ ] 发布\n\n```tsx\nconst theme = "bamboo";\n```'
    : '# Release notes\n\nSupports **Markdown**, tables, and task lists.\n\n> [!TIP]\n> Use semantic colors to keep interfaces consistent.\n\n| Component | Status |\n| --- | --- |\n| Editor | Ready |\n| Markdown Viewer | Ready |\n\n- [x] Bilingual docs\n- [ ] Release\n\n```tsx\nconst theme = "bamboo";\n```';
  return (
    <MarkdownViewer
      content={content}
      className="w-full"
      labels={
        chinese
          ? {
              empty: "没有 Markdown 内容",
              note: "备注",
              tip: "提示",
              important: "重要",
              warning: "警告",
              caution: "注意",
              code: {
                copy: "复制代码",
                copied: "已复制",
                copyFailed: "复制失败",
                loading: "正在加载",
                error: "无法高亮代码",
                empty: "没有代码",
                expand: "展开",
                collapse: "收起",
                writing: "正在生成",
                ready: "就绪",
              },
            }
          : undefined
      }
    />
  );
}
````

## Installation

```bash
bunx --bun shadcn@latest add @sui/markdown-viewer
```

Install with the shadcn CLI or use the shared `@workspace/ui` package. Follow the [installation guide](/docs/installation) to configure the registry, load styles, and choose import aliases.

## Usage

```tsx
import { MarkdownViewer } from "@workspace/ui/components/markdown-viewer";

<MarkdownViewer content="# Release notes\n\nA **Markdown** document." />;
```

## Supported formatting

Supports headings, links, tables, task lists, strikethrough, line breaks, and fenced code. Fenced code, including blocks without a language, and indented code use [Code Viewer](/docs/components/code-viewer). Blocks without a language render as plain text and retain copying and line breaks. Inline code remains inline. GitHub-style `[!NOTE]`, `[!TIP]`, `[!IMPORTANT]`, `[!WARNING]`, and `[!CAUTION]` blocks have semantic visual treatments.

Heading anchors are scoped to each viewer instance. A Contents, Table of Contents, or TOC heading can generate a table of contents. Math syntax is parsed, but this component does not load a dedicated mathematical typesetting engine.

## HTML and editable content

Embedded HTML is parsed and sanitized before rendering. Common safe formatting, including `details` and `summary`, is retained; scripts and event-handler attributes are removed. The example lets you edit Markdown containing a disclosure and a script that is not executed. Unlike [Html Viewer](/docs/components/html-viewer), this component does not execute HTML scripts.

### Example: markdown-viewer-sanitized

```tsx
"use client";
import { Label } from "@workspace/ui/components/label";
import { MarkdownViewer } from "@workspace/ui/components/markdown-viewer";
import { Textarea } from "@workspace/ui/components/textarea";
import { useId, useState } from "react";
import type { ExampleProps } from "../types";
export default function Example({ locale }: ExampleProps) {
  const chinese = locale === "zh-CN";
  const id = useId();
  const [content, setContent] = useState(
    chinese
      ? '## 可编辑的内容\n\n<details><summary>展开详情</summary>允许的 HTML 会保留。</details>\n\n<script>alert("removed")</script>'
      : '## Editable content\n\n<details><summary>Show details</summary>Allowed HTML is preserved.</details>\n\n<script>alert("removed")</script>',
  );
  return (
    <div className="grid w-full gap-4">
      <Label htmlFor={id}>
        {chinese ? "Markdown 源码" : "Markdown source"}
      </Label>
      <Textarea
        id={id}
        rows={5}
        value={content}
        onChange={(event) => setContent(event.target.value)}
      />
      <MarkdownViewer
        content={content}
        labels={
          chinese
            ? {
                empty: "没有 Markdown 内容",
                note: "备注",
                tip: "提示",
                important: "重要",
                warning: "警告",
                caution: "注意",
                code: {
                  copy: "复制代码",
                  copied: "已复制",
                  copyFailed: "复制失败",
                  loading: "正在加载",
                  error: "无法高亮代码",
                  empty: "没有代码",
                  expand: "展开",
                  collapse: "收起",
                  writing: "正在生成",
                  ready: "就绪",
                },
              }
            : undefined
        }
      />
    </div>
  );
}
```

## Theme and localization

The content follows the surrounding theme unless `theme` is supplied. Use `className` for container layout. `labels.empty` customizes the empty state, while `note`, `tip`, `important`, `warning`, and `caution` translate alert headings. `labels.code` accepts [CodeViewer labels](/docs/components/code-viewer#api-reference) for embedded code blocks, including copy, loading, and failure feedback. Markdown content itself is provided by your application and is not translated automatically.

## API reference

| Prop | Type | Default / behavior |
| --- | --- | --- |
| `content` | `string` | Required Markdown source. |
| `theme` | `"light" \| "dark"` | Follows surrounding theme. |
| `className` | `string` | Container layout classes. |
| `labels` | `Partial<MarkdownViewerLabels>` | Empty and alert labels; `code` translates embedded CodeViewer feedback. Defaults to English. |
| `glass` | `boolean` | `false`. |

The module exports `MarkdownViewerProps` and `MarkdownViewerLabels`. Rendering uses [react-markdown](https://github.com/remarkjs/react-markdown).
