Communitygithub.com

mariosakka/report-to-pdf

將 Markdown 報告(包含標題、段落、清單、帶有 Pygments 語法高亮的程式碼區塊、表格、粗體/斜體/行內程式碼以及可選的 YAML 型前置資料)渲染成精美、風格一致的 PDF — 包含品牌色條和可選標誌的標題頁、頁首/頁尾、自動生成且帶縮排的可點擊跳轉目錄、三層標題層級、斑馬紋邊框表格,以及可選的深色主題。

report-to-pdf 是什麼?

這個技能提供了一個確定性的、腳本驅動的 Markdown 轉 PDF 渲染器。它使用自訂的區塊解析器解析受限的「報告」Markdown 子集,並透過 `fpdf2` 進行排版,產生風格統一的 PDF。主要功能包括自動生成帶有可點擊頁碼連結、縮排的目錄;支援三層標題層級(主要、次要、第三級);可顯示帶有 Pygments 真實語法高亮的程式碼區塊;以及可選的深色主題。此技能的關鍵優勢在於其「確定性」:針對相同的輸入,每次都會產生完全相同的 PDF 輸出,確保了品牌一致性和結果的可重複性,且渲染過程中不涉及 LLM。它支援在 Cursor 和 Codex 等 CLI 環境中運作,透過 `python3 <skill-dir>/scripts/build_report_pdf.py <input.md> [options]` 指令執行,並可自動安裝 `fpdf2`、`Pillow` 和 `Pygments` 等依賴項。

相容平台✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/mariosakka/my-agent-skills/tree/HEAD/plugins/general/skills/report-to-pdf

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

預覽

來自技能 README

替代文字
替代文字

說明文件

report-to-pdf — 將 Markdown 報告轉換為精美 PDF

確定性、腳本驅動的 Markdown 轉 PDF 渲染器。它使用一個小型的自製區塊解析器(無外部 Markdown 函式庫)來解析受限的「報告」Markdown 子集,並透過 fpdf2 進行排版,其視覺慣例與 ColeteOnline Magento 模組的 build-user-guide.py 產生器相同 — 包含標題頁、頁首/頁尾、目錄、強調色條的章節標題、帶陰影的程式碼區塊以及邊框/斑馬紋表格。對於相同的輸入,佈局邏輯在每次執行之間保持不變:相同的報告輸入,每次產生相同的 PDF 輸出 — 渲染循環中沒有 LLM 參與。

使用時機

  • 「將這份 Markdown 審查報告轉換成 PDF 給導師。」
  • 「將我的報告匯出為精美的 PDF。」
  • 「我希望每次呈現的結果都相同,而不是每次執行都被 LLM 重新格式化。」
  • 任何包含標題、清單、程式碼區塊或表格,且需要客戶/導師/品牌品質 PDF 版本的 .md 報告或文件。

如何執行

python3 <skill-dir>/scripts/build_report_pdf.py <input.md> [選項]

(<skill-dir> 是此技能的基礎目錄,即包含此 SKILL.md 的資料夾。)

選項:

  • -o / --output <路徑> — 輸出 PDF 的路徑(預設為在原始檔旁邊產生 <input>.pdf)。
  • --logo <路徑> — 標題頁上的可選標誌圖片(PNG/WebP/JPEG,只要是 Pillow 能開啟的格式即可)。重複此旗標可放置多個標誌,它們會並排繪製在一行(也可以透過前置資料 logo: a.png, b.png 設定,路徑相對於 .md 檔案)。
  • --title、--subtitle、--version、--vendor、--author — 覆蓋對應的前置資料值(見下方說明);命令列旗標優先。
  • --cover center|left — 封面頁佈局。兩種模式下,整個標題區塊(標誌、標題、副標題、作者、版本)都會垂直居中;center(預設)還會水平居中,而 left 則靠左對齊。也可透過前置資料 cover: 設定。
  • --no-header — 省略頁首及其保留的空間,使每頁的內容從相同的頂部邊距開始(也可透過前置資料 header: false 設定)。
  • --accent "R,G,B" — 覆蓋用於標題頁頂部條和章節標題強調條的強調色(預設為 220,50,50,ColeteOnline 紅色)。
  • --dark — 使用深色主題渲染,而非預設的淺色主題(也可透過前置資料 theme: dark 設定;如果兩者皆存在,--dark 優先)。請參閱下方的「深色主題」。

如果任何匯入失敗,腳本會透過 pip install --user 自動安裝 fpdf2、Pillow 和 Pygments,以模仿參考腳本的 Pillow 自動安裝。這三個套件在開發過程中都經過驗證可以匯入,並且腳本已經過端到端測試(請參閱下方的「測試」)。

它預期的 Markdown 慣例

在檔案最頂端的可選前置資料區塊:

---
title: 我的報告標題
subtitle: 一行副標題
version: 1.0
vendor: ColeteOnline SRL
accent: 220,50,50
---

所有鍵都是可選的,並有合理的備用值:

  • title — 備用為在內文中找到的第一個 # H1 標題,然後備用為輸入檔名。
  • subtitle — 備用為空白(在標題頁上省略)。
  • version — 備用為今天的日期(YYYY-MM-DD);設定 version: none 可隱藏版本行。
  • vendor — 備用為空白(如果未設定,則在標題頁頁尾省略版權行)。
  • author — 作者姓名,顯示在封面頁的副標題下方(例如 author: 張三, 李四)。如果未設定則省略。
  • cover — center(預設)或 left;請參閱上面的 --cover。
  • header — 設定為 false 可省略頁首;請參閱 --no-header。
  • justify — 設定為 true 可將正文、標題和表格單元格內容左右對齊;預設為靠左對齊(對齊文字會在短換行行上拉伸單詞間距,例如兩行標題)。
  • accent — 備用為 ColeteOnline 品牌紅色 220,50,50。

內文 Markdown,以及每個元素的渲染方式:

Markdown渲染為
# 標題檔案中第一個 # 僅作為標題頁的標題(被消耗,不會在內文中重複)。之後出現的任何 # 都是真正的章節標題(見下方)。
# 主要章節(在第一個 # 之後)主要標題。 始終從新的一頁開始(除非游標已經在空白頁的頂部),帶有大的彩色左側條,粗體 16pt,黑色文字 — 並會在目錄中產生一個條目。僅用於真正的頂層劃分;每個章節會佔用一頁。
## 小節副標題。 粗體 13pt,強調色文字,帶有短的強調色底線(在視覺上與上下層級區分開來)— 不會強制分頁,而是繼續當前的排版流程。仍然會在目錄中產生一個條目。它有一個「避免標題獨自留在頁面底部」的檢查。
### 子小節(以及 ####+)第三級標題。 粗體 12pt,中性灰色,全寬細線,不分頁,不在目錄中產生條目(保持目錄的可掃描性)。
段落文字靠左對齊的正文段落,10pt。
- 項目 / * 項目項目符號清單(•)。
1. 項目編號清單。
```語言 ... ```帶陰影和邊框的等寬字體程式碼區塊;語言標記(如果存在的話)會以小的斜體標籤印在區塊上方,並驅動真正的 Pygments 語法高亮 — 見下方。
| a | b | 並帶有 --- 分隔行帶邊框的表格,粗體標題行,斑馬紋主體行,文字自動換行的單元格,等寬列。
獨佔一行的 --- / *** / ___垂直間距(不是分頁)。
獨佔一行的 <br>一個明確的空白主體行(5.5mm)。疊加數個以獲得更多空間。渲染器在頁面頂部不會自動添加間距,因此當您需要額外空間時請使用此標記。
獨佔一行的 <!-- pagebreak -->開始新的一頁(如果已在頁面頂部則無效)。
獨佔一行的 ![替代文字](路徑)居中、帶邊框的圖片,按比例縮放以適應;相對路徑會相對於 .md 檔案的資料夾解析。支援 PNG/JPEG/WebP 和 SVG(見「圖形、方框和數學公式」)。小於 900 像素寬的點陣圖圖片被限制在大約 130x105mm;圖形(圖片後接說明文字)、任何 SVG 以及寬度為 900 像素或以上的圖片可能使用完整的文字寬度(最大高度 120mm)。如果一個圖形無法放入頁面上的剩餘空間,它會被縮小以適應(最多縮小到其高度的 70%),而不是跳到下一頁並留下空白。
*圖片說明:...*(緊接在圖片後方的完整斜體行)圖片的說明文字:小字、居中、斜體,並與圖片保持在同一頁。替代文字永遠不會被印出。
> 文字 行定義框:每個引用區塊一個帶邊框和淺色陰影的框(粗體術語和行內數學可以出現在內部;獨佔一行的 > 且後面無內容,則在同一框中開始一個新段落)。
$...$行內數學,轉換為 Unicode 文字(希臘字母、≤ ≥ × ·、上下標、\frac{a}{b} -> (a)/b、\sqrt、\text{}、重音符號)。像 $5 這樣的價格不會被視為數學。
$$...$$(一行,或獨佔數行)顯示數學,來自第一個可用的數學後端(見「圖形、方框和數學公式」)的居中圖片。
空白行後帶有 4 個空格縮排的區塊沒有語言標籤的程式碼區塊(筆記本匯出會以這種方式印出單元格輸出)。不會緊接在清單之後應用。
**粗體**真正的粗體文字,透過 fpdf2 內建的 markdown=True 渲染器實現。
[文字](網址)一個真正的、可點擊的 PDF 鏈接註釋 — 只顯示文字,不顯示原始 URL — 並以獨特的鏈接顏色樣式顯示。
*斜體* / _斜體_渲染為斜體(內部轉換為 fpdf2 原生的 __italic__ 形式)。
`行內程式碼`行內程式碼的反引號會被移除 — 不支援等寬字體行內顯示,渲染為純文字。

標題、段落、項目符號、編號項目和表格單元格都透過 fpdf2 的 markdown=True 路徑渲染,因此 粗體 和 [文字](網址) 連結可以在所有出現文字的地方運作,包括在標題和表格單元格內部。圍柵式程式碼區塊是唯一的例外 — 其內容完全按字面渲染(不進行 Markdown 解析),因此包含字面 **、__ 或 []() 的程式碼範例不會被誤解。

圖形、方框和數學公式

設計使得筆記本的 Markdown 配套檔案(nbconvert 輸出)可以直接渲染:report-to-pdf notebook.md 取代了單獨的基於 Chrome 的 PDF 步驟。

SVG 圖片。 ![替代文字](figure.svg) 可以運作。fpdf2 自身的 SVG 繪圖會跳過 <marker> 箭頭、濾鏡和遮罩,使用核心字體(無希臘字母)繪製文字,並對沒有 fill 屬性的文字著色錯誤,因此每個 SVG 都會以 2.5 倍縮放柵格化並嵌入為 PNG,依序使用:無頭 Chrome/Edge(自動尋找;設定 REPORT_PDF_BROWSER 為瀏覽器路徑以覆蓋),然後是 cairosvg(如果可匯入)。如果兩者都不可用,SVG 將由 fpdf2 原生繪製,並會顯示警告說可能不完整。柵格化會依執行快取。

顯示數學後端(--math auto|latex|mathtext|unicode,或前置資料 math:;預設為 auto)。腳本會印出使用了哪個後端。

  1. latex:當 pdflatex、xelatex 或 tectonic 在 PATH 中時(加上 pdftocairo、PyMuPDF 或 dvisvgm 來生成圖片),或 latex + dvipng 時。每個公式都會使用 standalone、amsmath、amssymb 和 xcolor 以 12pt 編譯,然後裁剪為文字顏色的透明 300 dpi PNG。安裝:MiKTeX(Windows)、TeX Live(apt install texlive-latex-base texlive-latex-extra poppler-utils,macOS brew install --cask mactex-no-gui)或 tectonic(單一二進位檔案,按需下載套件;conda install -c conda-forge tectonic 或 scoop install tectonic;在 Windows 上使用 PyMuPDF 作為圖片轉換器進行了端到端測試)。
  2. mathtext:matplotlib 的 LaTeX 子集(分數、求和、希臘字母,\text{} 被映射為 \mathrm)。不需要 TeX,只需要 matplotlib。不支援 aligned 等環境,會失敗。
  3. unicode:與行內數學相同的文字轉換,居中。

缺失或失敗的後端(例如 TeX 拒絕的公式)會靜默地降級到下一個後端;--math latex 仍然以相同的方式降級。

測試:python tests/run_checks.py(數學轉換、解析器、SVG 路由、帶有模擬 PATH 的後端降級、tests/fixture.md 的端到端構建)。渲染配套檔案:python scripts/build_report_pdf.py notebook.md -o notebook.pdf。

語法高亮

圍柵式程式碼區塊使用真正的 Pygments 詞法分析器進行標記化(不是自製的正則表達式高亮器 — 程式碼正是那種小型臨時解析器容易出錯的東西:字串跳脫、巢狀註解、模板字面量)。圍柵上的語言標籤(```typescript、```sql、```python,…)選擇詞法分析器;一些常見的別名會被正規化(ts/tsx → typescript、js/jsx → javascript、sh/shell/zsh → bash、yml → yaml、prisma → graphql — 最接近的內建詞法分析器,在實踐中是不錯的匹配,因為 Prisma 的 @attribute(...) 語法和 GraphQL 的 @directive(...) 語法幾乎以完全相同的方式進行標記化)。

高亮是附加功能,從來不是渲染程式碼區塊的必要條件 — 缺失語言標籤、Pygments 無法識別的語言(即使在別名表之後)、或者 Pygments 本身無法匯入,都會回退到完全的高亮前行為:整個區塊使用一種平面顏色,不會崩潰,也不會遺失內容。

調色板(選擇用於在程式碼區塊的淺灰色背景上提高可讀性,不與任何特定的 Pygments 主題掛鉤):

Token 類別顏色
關鍵字(interface、async、const、NOT NULL、型別關鍵字如 string/number)洋紅色
字串綠色
數字棕色/橙色
註解灰色
函式/類別名稱、裝飾器/屬性(@map、@relation)藍色 / 棕色
內建物件(Promise 等)青色
其他所有內容(識別碼、標點符號、運算子)基礎程式碼顏色

調色盤中沒有完全對應條目的 Token 類型會透過遍歷 Pygments 的 Token 類型層級結構(例如,Keyword.Declaration 沒有自己的條目,但其父級 Keyword 有)直到找到匹配項來解析 — 純 Token 根節點始終匹配,因此這永遠不會無法解析為某種顏色。

等寬字體縮小以適應的邏輯(對於太寬而無法放入頁面的程式碼行,會均勻縮小整個區塊的字體,而不是溢出)不受高亮影響 — 它測量的是純字元寬度,這不會根據 Token 最終繪製的顏色而改變。

深色主題

傳遞 --dark,或在前置資料中設定 theme: dark,可以將整個文件渲染為深色主題,而不是預設的淺色主題。文件中的每一種顏色都會翻轉為適合深色的對應顏色 — 而不僅僅是程式碼區塊:

  • 頁面背景本身會被填充為深色(fpdf2 沒有原生的「頁面背景顏色」設定,因此這是透過在 header() 鉤子中填充整個頁面來實現的,在所有其他內容繪製之前 — 包括在標題頁上)。
  • 正文、標題(所有三個層級)、灰色/頁尾文字、分隔線、表格斑馬紋以及頁首/頁尾都使用單獨的一組深色模式顏色,而不僅僅是反轉淺色模式。
  • 語法高亮使用其自己的深色模式調色板(選擇更亮的粉紅色/綠色/藍色以在深色程式碼背景下形成對比),而不是將淺色模式的顏色調暗。
  • 連結顏色(包括 [文字](網址) Markdown 連結和目錄的跳轉到頁面連結)切換到在深色背景上仍可讀的較淺藍色。

--accent 顏色(頂部條、主要標題左側條和副標題文字/底線)在兩種主題中都保持不變 — 如果您計劃在兩種主題中生成相同的報告,請選擇一種在白色和近黑色背景下都有效的顏色,或者如果情況並非如此,則每個主題單獨覆蓋 --accent。

目錄

回填的目錄(見上方的「渲染方式」)

…

[為翻譯而截斷]

相關技能