# 以 NanoMD 渲染

自 v1.2.2 起，瀏覽器儀表板以 [NanoMD](https://nanomd.pardn.io) 渲染 agent 回覆與 Markdown 檔，圖表、流程圖與數學公式直接顯示為圖，不再是原始碼。

## 可渲染的內容

| Markdown | 結果 |
| --- | --- |
| ```` ```chartjs ````，內容為 `{"type": ..., "data": {...}}` | 圖表：bar、line、pie、doughnut、radar、polarArea、scatter、bubble |
| ```` ```mermaid ```` | 圖：flowchart、sequenceDiagram、stateDiagram-v2、classDiagram、erDiagram、gantt、timeline |
| ```` ```math ```` 或行內 `$...$` | KaTeX 數學公式 |
| 其他程式碼區塊 | 語法高亮，附複製按鈕 |
| GFM 表格、待辦清單、註腳、`==highlight==`、`> [!NOTE]` 提示框 | 套用樣式的 Markdown |

無法解析的區塊（JSON 錯誤、不支援的圖表類型、Mermaid 語法錯誤）改顯示原始碼。本頁同樣由 NanoMD 渲染，完整範例見下方「完整渲染測試」。

## 完整渲染測試

以下測試文件涵蓋儀表板宣告支援的所有語法，本頁以同一套 NanoMD 渲染。這份文件測試目前介面宣告支援的 CommonMark、GFM 與自訂擴充。圖表數值都是測試資料；外部圖片、影音能否載入取決於網路與介面限制。文件已提供測試案例，並不代表每個案例都經過畫面驗證。

### 基本排版

一般文字，**粗體**、*斜體*、***粗斜體***、~~刪除線~~、==重點標示==、`行內程式碼`。

下標：H~2~O。上標：x^2^。

這是第一段。

這是第二段。下一行使用兩個行尾空白強制換行。  
這一行應在同一段落內換行。

#### 標題層級測試

##### 第四層標題

###### 第五層標題

###### 第六層標題

### 替代式標題

---

### 清單與引用

- 無序清單
  - 巢狀清單
    - 更深一層
- **粗體清單項目**

1. 有序項目甲
2. 有序項目乙
   - 有序清單內的無序項目

- [x] 已完成工作
- [ ] 尚未完成工作

> 一般引用。
>
> 引用的第二段。
>
> > 巢狀引用。

> [!NOTE]
> 這是補充資訊提示。

> [!TIP]
> 這是操作建議提示。

> [!IMPORTANT]
> 這是重要資訊提示。

> [!WARNING]
> 這是警告提示。

> [!CAUTION]
> 這是需要謹慎處理的提示。

### 表格

| 靠左 | 置中 | 靠右 |
| :--- | :---: | ---: |
| **粗體** | `程式碼` | 一般文字 |
| 含跳脫字元 \| | ==重點== | ~~刪除~~ |

### 連結、跳脫與註腳

[一般連結：CommonMark](https://commonmark.org/)

<https://commonmark.org/>

[參照式連結][commonmark]

[commonmark]: https://commonmark.org/ "CommonMark 官方網站"

跳脫符號：\*不是斜體\*、\#不是標題、\[不是連結\]、\$不是數學起始符號。

這一句有數字註腳。[^1] 這一句有具名註腳。[^note]

### 程式碼

```javascript
const message = "繁體中文程式碼測試";
console.log(message);
```

```python
def greet(name):
    return f"你好，{name}！"
```

縮排式程式碼：

    const indented = true;
    console.log(indented);

外層四個反引號，應完整保留內層三個反引號：

````markdown
**這裡不應呈現粗體，而是顯示原始碼**

```javascript
console.log("巢狀程式碼圍欄");
```
````

### 數學公式

行內公式：$a^2+b^2=c^2$。

展示公式：

```math
\int_a^b f(x)\,dx = F(b)-F(a)
```

```math
\mathbf{A}=\begin{pmatrix}a&b\\c&d\end{pmatrix}
```

以下使用 `latex` 標籤，預期只顯示原始碼，不渲染成公式：

```latex
E=mc^2
```

### Chart.js 圖表

下列皆為無單位測試資料，不代表真實統計。

#### 長條圖

| 類別 | 測試值 |
| :--- | ---: |
| 甲 | 12 |
| 乙 | 19 |
| 丙 | 7 |

```chartjs
{"type":"bar","data":{"labels":["甲","乙","丙"],"datasets":[{"label":"測試值","data":[12,19,7]}]}}
```

#### 折線圖

```chartjs
{"type":"line","data":{"labels":["甲","乙","丙"],"datasets":[{"label":"測試趨勢","data":[12,19,7]}]}}
```

#### 圓餅圖

```chartjs
{"type":"pie","data":{"labels":["甲","乙","丙"],"datasets":[{"label":"測試組成","data":[12,19,7]}]}}
```

#### 環圈圖

```chartjs
{"type":"doughnut","data":{"labels":["甲","乙","丙"],"datasets":[{"label":"測試組成","data":[12,19,7]}]}}
```

#### 雷達圖

```chartjs
{"type":"radar","data":{"labels":["甲","乙","丙"],"datasets":[{"label":"測試輪廓","data":[12,19,7]}]}}
```

#### 極區圖

```chartjs
{"type":"polarArea","data":{"labels":["甲","乙","丙"],"datasets":[{"label":"測試分布","data":[12,19,7]}]}}
```

#### 散佈圖

```chartjs
{"type":"scatter","data":{"datasets":[{"label":"測試點","data":[{"x":1,"y":12},{"x":2,"y":19},{"x":3,"y":7}]}]}}
```

#### 氣泡圖

```chartjs
{"type":"bubble","data":{"datasets":[{"label":"測試氣泡","data":[{"x":1,"y":12,"r":6},{"x":2,"y":19,"r":10},{"x":3,"y":7,"r":8}]}]}}
```

### Mermaid 圖表

#### 流程圖

```mermaid
flowchart LR
    A[輸入] --> B{檢查}
    B -->|通過| C[呈現]
    B -->|未通過| D[顯示原始碼]
```

#### 循序圖

```mermaid
sequenceDiagram
    participant U as 使用者
    participant R as 渲染器
    U->>R: 提交 Markdown
    R-->>U: 顯示內容
```

#### 狀態圖

```mermaid
stateDiagram-v2
    [*] --> Pending
    Pending --> Rendering
    Rendering --> Done
    Done --> [*]
```

#### 類別圖

```mermaid
classDiagram
    class Document {
        +String title
        +render()
    }
    class Renderer {
        +parse()
    }
    Document --> Renderer : uses
```

#### 實體關聯圖

```mermaid
erDiagram
    AUTHOR ||--o{ DOCUMENT : writes
    AUTHOR {
        string name
    }
    DOCUMENT {
        string title
    }
```

#### 甘特圖

```mermaid
gantt
    title 渲染測試排程（示意）
    dateFormat YYYY-MM-DD
    section 測試
    準備案例 :a, 2026-11-08, 1d
    檢視畫面 :b, after a, 1d
```

#### 時間軸

```mermaid
timeline
    title 測試階段
    準備 : 撰寫內容
    渲染 : 顯示內容
    檢視 : 人工確認
```

### 圖片與影音

這一節為外部資源嵌入測試；網址不保證在目前環境可以載入。

#### 一般圖片

![外部測試圖片](https://placehold.co/600x200/png?text=Markdown)

#### 固定寬高

![固定寬高測試](https://placehold.co/600x200/png?text=Fixed)(320x240)

#### 百分比寬度

![百分比寬度測試](https://placehold.co/600x200/png?text=Width)(50%x)

#### 固定高度

![固定高度測試](https://placehold.co/600x200/png?text=Height)(x120)

#### MP4 播放器

![MP4 測試影片](https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4)

#### MOV 播放器語法

以下為刻意使用保留網域的語法案例：可測試是否識別為播放器，但不會有實際影片可播。

![MOV 語法測試，無實際媒體](https://example.com/test.mov)

#### YouTube 裸網址

https://www.youtube.com/watch?v=aqz-KE-bpKQ

#### Vimeo 連結

[Vimeo 嵌入測試](https://vimeo.com/76979871)

### 預期退回原始碼的案例

以下故意提供無效或不支援的內容，預期顯示原始碼，不影響後續段落。

無效的 Chart.js JSON：

```chartjs
{"type":"bar","data": }
```

缺少 `data`：

```chartjs
{"type":"bar"}
```

不支援的圖表類型：

```chartjs
{"type":"unsupported","data":{"labels":[],"datasets":[]}}
```

無效的 Mermaid 語法：

```mermaid
this is not a valid diagram
```

### 測試邊界

- 原始 HTML、CSS、JavaScript 執行、摺疊區塊與其他未宣告的語法不列為保證支援項目。
- 外部影音若因防追蹤、內容安全政策、網路或來源網站限制而無法載入，不必然代表 Markdown 語法失效。
- 這是測試文件，未進行螢幕截圖或瀏覽器逐項驗證。

[^1]: 這是數字註腳內容，應出現在註腳區並提供導覽。
[^note]: 這是具名註腳，支援 **粗體** 與 [連結](https://commonmark.org/)。

## 渲染的位置

| 介面 | 行為 |
| --- | --- |
| Web 對話回覆與推理區塊（`chat-` session） | 串流時即渲染；較早訊息中的圖在捲入畫面時才渲染 |
| 回覆中的 `.md`、`.markdown`、`.txt` 檔案連結 | 在側邊面板開啟並以 NanoMD 渲染；本機圖片經 `/v1/file/open` 載入 |
| TUI、Telegram、Discord | 顯示 Markdown 原始碼 |

## Agent 如何運用

System prompt 會告訴 agent 圖表在哪裡能渲染。`chat-` session 中，對話回覆與 `.md` 檔都會附圖；其他 session 只放在 `.md` 檔，因為這些對話介面只會顯示原始區塊。內容含 3 個以上項目或時間點的數字、流程或公式時，agent 會主動在對應的表格或文字旁附上圖表、流程圖或公式，不需使用者要求；只重述單一數字或兩項比較時則不附圖。

## 關於 NanoMD

NanoMD 是 TypeScript 撰寫的 Markdown parser，將 Markdown 轉為經過消毒的 HTML 與 JSON AST，頁面用到時才載入 Mermaid、KaTeX 與 Chart.js。Agenvoy 在 `page/vendor.json` 固定 parser 與樣式表版本（v1.2.2 為 2.0.10），daemon 下載一次到 `~/.config/agenvoy/vendor/nanomd/` 後由本機提供，離線也能渲染。語法參考與線上試用：[nanomd.pardn.io](https://nanomd.pardn.io)。

另見：[瀏覽器儀表板](/zh/getting-started-browser)。
