SWISS-PDF · 瑞士國際排版 PDF 生成工具
將 md / docx / txt / html 一鍵排成瑞士國際排版風格的 A4 PDF。
白底黑字、極細分割線、大號章節數字、等寬數字、唯一彩色紅 #E5484D。
設計標記取自一套瑞士國際主義版式的精裝冊(大號章節數字、極細分割線、單一強調色), 改為單流自動分頁,因此任意長度的文件都能直接處理。
如何使用
方式一:拖拽(推薦)
將檔案拖到 swiss-pdf.bat 上 → 同目錄生成同名 .pdf,同時保留一份 xxx.pdf-src.html(可複查的 HTML 源)。
方式二:命令列
python make.py 輸入檔案 # 出 PDF
python make.py 輸入檔案 --html # 只出 HTML(存成 xxx.html,瀏覽器打開可手動列印)
python make.py 輸入檔案 -o 輸出.pdf
python make.py a.md b.docx c.txt # 批量
python make.py 輸入檔案 --no-cover --no-toc
python make.py 輸入檔案 --title "標題" --kick "眉註" --date 2026.11.09
支援的輸入格式
| 格式 | 轉換方式 | 說明 |
|---|---|---|
.md | pandoc | 支援 YAML front-matter、GFM 表格、列表、程式碼區塊、圖片 |
.docx | pandoc | 標題樣式 → 章節標題;表格 → 樣式表;圖片自動提取 |
.txt | 內建解析 | 空行分段;短行帶編號(一、/ 1. / 第X章)→ 章節標題 |
.html | 內建解析 | 取 <body>,去掉 script/style;<title> 作為文件標題 |
封面:YAML front-matter
寫在 md 最頂部即可(其他格式靠 --title 等參數):
---
title: 城市騎行安全白皮書
subtitle: 基於三城抽樣調查的觀察與建議
kick: 交通治理研究
en: Urban Cycling Safety White Paper
slug: 城市騎行安全
nature: 公開版
project: 城市慢行系統研究計畫
party_a: 委託方名稱
party_b: 受託方名稱
stage: 調研 → 撰寫 → 定稿
source: 01_觀測記錄 02_訪談紀要 03_方案
date: 2026.11.10
version: v2.1
badges: 公開; !重點; 數據支撐
---
badges用;分隔,前綴!的為黑底反白。- 未填
date時自動使用當天日期。 - 不加 front-matter 也能執行,封面只顯示標題 + 日期 + 版本空位。
正文:六種風格塊
markdown 裡用 ::: 包起來(區塊內每行 = 一個條目):
::: note
補充說明、口徑提醒。灰底。
:::
::: quote
關鍵結論引文,左側 3pt 豎線。
:::
::: inverse
黑底反白區塊,放置最重的一句話。
:::
::: warn
紅框警示,唯一允許使用彩色的位置。
:::
::: stat
4,280 | 觀測樣本總數 || 24 | 觀測點位 || 3 | 覆蓋城市
:::
::: check
早高峰通勤路口(需 7:30 前到位)
夜間照明路段(需補光燈)
:::
::: kv
頁數 | A 方案 20 頁 / C 方案 32 頁
推薦 | 方案 C,但需補足第二城數據
:::
stat 用 數字 | 說明 組成一格,|| 分隔。kv 用 鍵 | 值。
自動行為
| 行為 | 規則 |
|---|---|
| 章節編號 | # 一級標題 → 大號數字 00/01/02…;標題已含「01 」「一、」編號時沿用 |
| 目錄 | 章節 + ## 小節合計 ≥ 5 條時才生成,否則省略此頁;章節標題帶錨點,PDF 內可點擊跳轉 |
| 表格 | 列數 ≥ 6 自動降字號(table.wide);純數字儲存格右對齊 + 等寬字體 |
| 頁眉頁腳 | 封面頁不排版;正文頁眉左側運行標題、頁腳右側「第 i 頁 / 共 N 頁」 |
| 列印 | @page A4,邊距 14/15/13mm;標題不與正文分離,表格行不跨頁斷開 |
HTML 源的額外處理(實測補充)
源碼是「自帶設計的網頁」時,本技能會自動進行以下標準化,避免重排後出現游離編號或重複標題:
| 源碼結構 | 處理 |
|---|---|
<div class="sec-head"><span class="sec-num">3</span><h2>題</h2></div> | 轉成模板的 .sec 章節頭(編號取 span,標題取 h2) |
<h1>03 題</h1> / <h1>題</h1> | 同上;無編號則按出現順序自增 |
單獨成段的純數字 <p>0</p> | 丟棄(常見於把章節號當裝飾數字的寫法) |
<header class="masthead"> / <nav> | 丟棄(封面已另起,重複的 kicker/大標題/落地目錄會污染正文) |
<section> 分節 | 保留為分節容器,標題仍需 sec-head 或 h1 才能進入目錄 |
<div id="xxx" class="chart"> + echarts | 用無頭瀏覽器截圖成 PNG 再嵌入;截圖前等待 networkidle + 2.5s |
圖表截圖的前提:echarts 走 CDN 時需能連網;離線環境請在源碼中內聯 echarts.min.js。
字體與標點
字體:倉庫內置思源黑體,@font-face 內聯
fonts/ 裡隨倉庫攜帶兩個檔案,make.py 在生成 HTML 時將它們的 base64 內聯進 <style>,
註冊成字體族 Swiss Sans SC:
| 檔案 | 字重 |
|---|---|
SourceHanSansCN-Regular.subset.ttf | 400 |
SourceHanSansCN-Bold.subset.ttf | 700 |
子集範圍約 7100 字符(ASCII + 中英標點符號 + GB2312 全部 6763 漢字),字符集見 fonts/charset.txt。
好處:換一台沒裝思源的機器,輸出完全一致,不需要用戶安裝字體。
用戶可自行更換或下載字體,三種做法(詳見 fonts/README.md):
- 替換檔案(推薦):把自己的 TTF 改名成上述兩個檔案名稱覆蓋。先進行子集化,否則 HTML 帶上完整 10 MB:
pyftsubset 你的字體-Regular.ttf --text-file=fonts/charset.txt --output-file=fonts/SourceHanSansCN-Regular.subset.ttf - 刪掉
fonts/:make.py偵測不到檔案就跳過@font-face,回退 CSS 裡的系統字體堆疊 (思源黑體 SC/CN → Noto Sans SC → Noto Sans CJK SC → 夢源黑體 CN → PingFang SC → Segoe UI Symbol)。 - 只改 CSS:修改
templates/swiss.css頂部--sans第一個字體名稱。
⚠️ 必須使用 .ttf(TrueType 輪廓),不可使用 .otf(CFF)。 Chromium 列印 PDF 時會將 CFF 的
Web 字體降級成 Type3 字形指令(每個字形儲存一段繪圖路徑),體積膨脹數倍。同一份 4 頁文件:
OTF → 328 KB / 205 個 Type3;TTF → 79 KB / 1 個 Type3。
微軟雅黑在 Chromium 下缺少 ·(U+00B7)、→ ↓ ≤ ≥ 等符號字形,會導致顯示為方框,因此已從主要字體堆疊中移除。
引號:全文強制國標彎引號
convert.normalize_quotes() 在轉換的最後一步統一處理,覆蓋標題、封面、頁眉、目錄、表格、風格塊:
| 輸入 | 輸出 |
|---|---|
「」 | “” |
『』 | ‘’ |
程式碼裡的直引號 " ' | markdown 走 pandoc +smart 自動轉彎引號;程式碼區塊 <code> / <pre> 內不動 |
實現僅替換 4 個碼位(U+300C/D/E/F → U+201C/D/8/9),不影響 HTML 標籤屬性與 CSS/JS。
已驗證的實跑記錄
| 輸入 | 規模 | 頁數 | 耗時 |
|---|---|---|---|
| md | 29 KB | 15 | ~6s |
| html | 105 KB + 2 個 echarts 圖 | 21 | ~15s |
| docx | 標題樣式 + 表格 | 2 | ~6s |
txt(samples/) | 1.2 KB | 2 | ~5s |
| md 長文件回歸 | 71 KB | 21 | ~24s |
環境依賴
| 依賴 | 本機狀態 | 缺失時 |
|---|---|---|
| pandoc(≥2.19) | 執行 pandoc -v 確認 | md/docx 無法轉換 |
| playwright + chromium | 或系統自帶 Chrome / Edge | 無法渲染 PDF |
| python-docx(可選) | 僅輔助解析 | 不影響主流程 |
指定瀏覽器:set SWISS_PDF_CHROME=<chrome.exe 的路徑>
檔案結構
swiss-pdf/
├── SKILL.md 本檔案
├── swiss-pdf.bat 拖拽入口
├── make.py 主流程:轉換 → 組裝 → 渲染
├── convert.py 各格式 → HTML 片段 + 區塊級語法
├── templates/
│ └── swiss.css 全部樣式(設計標記 + 列印規則)
└── samples/ 三種格式的對照範例
限制(無法做到的功能)
- 精裝冊那種手工分頁(每頁內容精心擺放、跨頁對開設計)樣板無法實現,仍需手寫 HTML。 本技能定位為「常規文件快速成稿」。
- 插圖排版依賴原文件的圖片尺寸,不做裁切與出血。
- 目錄右側印刷頁碼未實現(頁內元素無法取得頁碼);章節標題可點擊跳轉,頁腳有「第 i 頁 / 共 N 頁」。
- 過短的表格區塊可能被整塊推到下一頁(為避免鍵值表被拆分,
.kv區塊設為不可跨頁)。 - 複雜 Word 樣式(文字方塊、藝術字、多級編號列表)在 pandoc 轉換時會降級。