語法結構
Markdown+ 文件由 一份 H1 標題 + 一段引言 + 多個 bullet-list block 組成。每個 block 的開頭固定格式:
- **#<kebab-case-id>** `type:<value>` `<key>:<value>` ...
<block body, 縮排 2 spaces, 任意合法 Markdown>
- **#<child-id>** `type:<value>` ...
<子 block, 縮排 4 spaces>
組成元素
| 元件 | 規則 | 純 Markdown 渲染 | Markdown+ viewer 渲染 |
|---|---|---|---|
| Bullet | - | 圓點 | section 邊界 |
| Block ID | **#kebab-id** | 粗體 hashtag | anchor + id="" |
| Metadata | inline code `key:value` | monospace badge | 解析為 attribute |
| 父子 | nested bullet list 縮排 | 自然縮排 | <section> 巢狀 |
受控 metadata 字彙表
type: (block 主類型,closed list)
需要擴充必須用 x- 前綴。
| type | 用途 |
|---|---|
state | 描述當前事實 / 現況 |
history | 已不適用的歷史(預設摺疊) |
decision | 決策紀錄 |
record | 事件紀錄 (會議、incident) |
issue | 待解問題 / blocker |
note | 補充說明 |
spec | 規格 / 技術說明 |
task | 待辦 / action item |
reference | 外部連結彙整 |
figure / table / chart / diagram | 視覺資料 |
kpi / gauge / targets / dashboard / card | 儀表板元件 |
dialogue / turn | 對話容器與輪次 |
step | 教學 / runbook 步驟 |
status: (closed list)
draft
active
proposed
accepted
rejected
superseded
deprecated
archive
healthy
degraded
down
on-track
behind
exceeded
done
blocked
open
closed
其他常用 metadata
updated:YYYY-MM-DD— ISO 日期visibility:collapsed— viewer 預設摺疊priority:high|normal|low|criticaltags:[domain:auth,team:platform]— 用 namespacesuperseded-by:<id>— 指向替代者related:[id1,id2]variant-group:install+variant:mac— 同 group 的 sibling 會被 viewer 聚合成 tab- KPI:
value: target: delta: unit: - Gauge:
value: min: max: target: zones:[99:red,99.9:amber,99.95:green] keywords:a,b,c— block 關鍵詞清單。手動宣告永遠優先;未宣告時 viewer 會自動抽出(虛線 chip)。詳見 自動關鍵詞抽取
必須遵守的約束關係
status:deprecated⇒ 必有superseded-by:<id>type:history⇒visibility:collapsedtype:kpi⇒value:,且與 prose 段數字一致type:gauge⇒value: min: max: target: zones:全要- 同層共用
variant-group:的 sibling 必須各有不同variant: - 每個
figure / chart / table / kpi / gauge / video / audio必須有 prose companion 段 - 表格 > 30 列必須用
data-source:./data/<name>.csv
禁止清單 (lint error)
| 禁止項 | 替代 |
|---|---|
:::block fenced div | bullet list block |
Raw HTML 容器 (div / span / section ...) | 由 viewer 從 metadata 生成 |
<script> / <style> | 留給 viewer |
class="" / style="" | 留給 viewer |
Inline data:image/...;base64,... | 外部相對路徑 |
Raw <svg> 直接寫在段落或 HTML 容器內 | 包進 ```svg fence(<= 16 KB)或外部檔  |
```svg fence 內容 > 16 KB | 拆成 ./diagrams/*.svg 外部檔 |
| 巨型 inline chart spec (>80 行) | 拆到 ./charts/*.json |
| 巨型 inline 表格 (>30 列) | 拆到 ./data/*.csv |
寫死 caption 編號 (Figure 1:) | *Figure: ...*,viewer 自動編號 |
自由 type: 值 | 受控字彙表或 x- 前綴 |
視覺化 fence:```svg 與 ```mermaid
圖表 / 流程圖 / 簡單示意圖可以用兩種 標準 code fence 內聯, 在 GitHub / Obsidian 仍是合法的 code block(graceful degradation), 在 Markdown+ viewer 才長出 graph / code 切換 toolbar。
```svg — 內聯向量圖
- **#sla-trend** `type:figure` `media:svg`
*Figure: API SLA 月度趨勢*
```svg
<svg viewBox="0 0 320 120" xmlns="http://www.w3.org/2000/svg">
<polyline points="50,40 130,56 210,70 290,72" fill="none" stroke="#0ea5e9" stroke-width="2"/>
...
</svg>
```
4 月 SLA 跌至 99.92%,低於目標。
viewer 行為
| SVG 大小 | viewer 動作 | 說明 |
|---|---|---|
| ≤ 16 KB | 渲染圖 + graph / code 雙視圖 toolbar | toolbar 顯示 svg · X.Y KB |
| > 16 KB | 強制只顯示 code + warning callout | 提示拆成 ./diagrams/*.svg |
注入前 sanitize
<script>tag 整段移除on*=event handler attribute 全部去掉(onclick / onload / onerror …)- 結構標記(
<defs> <style> <marker> <filter>)保留
```mermaid — Mermaid 圖表
- **#refresh-flow** `type:diagram` `diagram-type:mermaid`
*Figure: Token refresh 流程*
```mermaid
sequenceDiagram
participant C as Client
participant G as Gateway
C->>G: request with expired token
G-->>C: new access token
```
refresh 流程從 client 看是透明的。
viewer 動態 import Mermaid 10 (CDN) 渲染為 SVG; toolbar 與 SVG fence 共用元件,「graph」視圖顯示渲染後的圖、 「code」視圖顯示原始 mermaid source。
自動抓取的結構關鍵詞
含 ```mermaid 的 block 自動帶
mermaid +
圖表類型(從 fence 第一個非空行偵測):
| fence 第一行 | 抽出的關鍵詞 |
|---|---|
sequenceDiagram | mermaid, sequenceDiagram |
flowchart TD | mermaid, flowchart |
classDiagram | mermaid, classDiagram |
gantt | mermaid, gantt |
graph LR | mermaid, graph |
stateDiagram / erDiagram / pie / ... | 同上規則,取 fence 第一個 identifier |
含 ```svg 的 block 則永遠帶
svg 作第一個關鍵詞。
自動關鍵詞抽取(無辭典)
每個 block 沒宣告 keywords: 時,
viewer 會用 純統計、無辭典依賴的演算法即時抽出
top-N 關鍵詞,在 block header 下方以虛線 chip 顯示。
手動宣告永遠優先;沒宣告才填 auto chip。
演算法 — N-gram + PMI + 左右熵
完全照「無詞典新詞發現」標準演算法實作,瀏覽器端純 JS 跑,毫秒級完成:
- 文本清理:剝除 code fence、inline code、image / link markdown、heading 標記、block header 行,僅保留 prose。
-
N-gram 枚舉:
- CJK 連續字串 2 ~ 8 字(
min_len=2, max_len=8) - ASCII token
[A-Za-z][A-Za-z0-9+\-]*並行抓取 (適用Markdown+ / block-based / SDK等混合語術語)
- CJK 連續字串 2 ~ 8 字(
-
內部凝固度(PMI cohesion):
對候選詞
w嘗試所有二分切分, 算PMI(x, y) = log(P(xy) / P(x)P(y))), 取 最小值作 cohesion(代表最弱的內部連結強度,反映「整體是否確實一起出現」)。 門檻min_pmi ≥ 1.0。 -
左右自由度(Shannon entropy):
收集候選詞左、右鄰字分佈,各計算 Shannon 熵。
兩端皆需
≥ 0.4。 熵高表示鄰字多樣 = 該詞能獨立出現(像「人工智慧」左右搭配很多), 熵低表示鄰字固定 = 是更長詞的一部分(像「式人工智」永遠夾在「生成式人工智慧」裡會被濾掉)。 -
詞頻過濾:出現次數
≥ 2。 -
綜合排序:
score = freq × min-PMI × min(left, right)-entropy, 降冪取 top-K(預設 80 個全域候選 → 每 block 取 top-5)。 - 子字串抑制:已 kept 的長詞會擠掉它的子字串 (若 freq 接近 ≥ 60%)——比如「人工智慧」入選後就會擠掉 只是它子字串的「人工」「智慧」。
-
每 block 投影:對該 block body 計算每個全域候選的命中次數,
block_score = global_score × log(occ + 1), 排序取 top-5。
結構標籤前置
以下兩類訊號 n-gram 抓不到(fence 內容被清理階段剝除),所以由獨立 helper 注入並 排在自動抽取詞之前:
- 含
```svgfence → 永遠先放svg - 含
```mermaidfence → 先放mermaid+ 圖表類型(見上)
預設參數一覽
| 參數 | 預設值 | 說明 |
|---|---|---|
min_len | 2 | CJK n-gram 最小長度 |
max_len | 8 | CJK n-gram 最大長度(中文詞通常 ≤ 6,留 buffer 抓「概念組合詞」) |
min_freq | 2 | 單檔場景的下限(大語料建議 ≥ 5) |
min_pmi | 1.0 | 單檔較寬鬆;大語料 PDF 建議 3 |
min_entropy | 0.4 | 左右兩端 Shannon 熵下限 |
min_ascii_len | 3 | ASCII token 最短長度(避開 `is`, `of` 等) |
topK | 80 / 5 | 全域 80,每 block 5 |
手動覆寫
把 keywords:a,b,c 放進 block header,viewer 就改顯示實線 chip,不再跑自動抽取。playground sub-header 的「寫入 keywords」按鈕會把 viewer 計算出的 auto 詞用 inline-code 形式寫進 source(``keywords:`a,b,c```),套用前 confirm dialog 列前 8 個 block 的建議供預覽。
複雜度
固定 L (最大候選長度)下,演算法是
O(N × L) 線性掃描 +
O(V log V) 排序。文件變 10 倍大、時間約 10 倍,不是平方。
記憶體主要是候選 Map,經 min_freq 過濾後規模有限。
設計理念對照
| 面向 | 傳統 Markdown | HTML | Markdown+ |
|---|---|---|---|
| 對 AI | 友善但難結構化 | tag 噪音、token 暴漲 | block-addressable + 受控 metadata |
| 對人類 | 陽春 | 漂亮但 source 不可讀 | viewer 渲染漂亮 + source 仍可讀 |
| 新 dialect | 無 | (N/A) | 無 — 仍是合法 CommonMark |
| 圖片 | 路徑或 base64 | 常用 base64 inline | 強制路徑,禁 base64 |
| 互動 UI | 無 | 需手寫 JS + CSS | 由 viewer 從 metadata 自動推導 |