逐步執行與相依性
- 請依序遵循此技能的工作流程。在步驟使用函式庫、命令列工具、執行環境或字型之前,僅檢查該步驟所需的相依性;不要預設它們已安裝。
- 重複使用已存在的相依性。如果缺少某個相依性,僅使用目前作業系統與可用的套件管理員安裝該相依性,然後驗證它並重試原始步驟。不要預先安裝整個相依性清單。
- 使用活躍的 Python 環境(
python -m pip install <套件名稱>,或相符的python);必要時建立任務專用的虛擬環境。在任務專案中安裝 Node.js 函式庫(npm install <套件名稱>),以便腳本能解析它們。對於系統工具與字型,使用可用的 OS 套件管理員(例如 macOS 上的 Homebrew,Debian/Ubuntu 上的 apt,或 Windows 上的 winget)。 - 當安裝需要核准時,遵循主機的權限流程。如果無法取得套件管理員或所需權限,或安裝/下載失敗,請回報缺少的相依性與受影響的步驟;不要無限期重試或宣稱該步驟已通過。在可能的情況下繼續執行獨立的步驟。
- 保持原始工作流程與品質檢查。僅在渲染需要時檢查字型。僅使用文字、內建工具或自包含 HTML 的步驟不需要安裝套件;外部工具存取或驗證必須透過主機處理,而非套件管理員。
路徑與執行環境約定(執行命令前必讀)
- Python 命令:本機使用
python(Windows 上通常無python3)。下文所有命令統一用python。 - 腳本路徑:本技能腳本位於
AppData/skills/pptx/scripts/(相對於專案根目錄)。下文及 editing.md / pptxgenjs.md 中的腳本命令均已寫為該基礎目錄下的絕對相對路徑,可直接從專案根目錄執行。 - 工作目錄:命令假設當前工作目錄為專案根目錄。若工作目錄不同(如
default_workdir被改為其他目錄),請將AppData/skills/pptx替換為技能目錄的絕對路徑。 - Node.js:執行
npm/node(pptxgenjs 需要)前,按專案規則把 Node.js 目錄加入 PATH。
PPTX 技能
快速參考
| 任務 | 指南 |
|---|---|
| 讀取/分析內容 | python -m markitdown presentation.pptx |
| 從範本編輯或建立 | 閱讀 editing.md — QA:validate_layout.py + markitdown |
| 從零建立 | 1. 規劃內容 → 2. 預先產生素材 → 3. 閱讀 pptxgenjs.md |
| 從設計上防止溢出 | 閱讀 pptxgenjs.md |
| 產生設計系統 | python AppData/skills/pptx/scripts/design/search.py "<主題>" --design-system |
| 產生後修正 | python AppData/skills/pptx/scripts/fix_pptx.py output.pptx |
| 版面 QA(重要優先) | python AppData/skills/pptx/scripts/validate_layout.py presentation.pptx |
讀取內容
# 文字擷取
python -m markitdown presentation.pptx
# 原始 XML
python AppData/skills/pptx/scripts/unpack.py presentation.pptx unpacked/
編輯工作流程
完整細節請閱讀 editing.md。
- 使用
markitdown分析範本 - 解包 + 樣式層檢查 + 主題與樣式對齊計畫
- 操作投影片 → 編輯內容 → 清理 → 封裝
- ⚠️ 版面 QA(強制關卡):
python AppData/skills/pptx/scripts/validate_layout.py output.pptx --slides <已編輯的投影片編號> - ⚠️ 內容 QA(強制):
python -m markitdown output.pptx
從零建立
完整細節請閱讀 pptxgenjs.md。
當沒有可用的範本或參考簡報時使用。
必要的投影片結構(僅限從零建立)
從零建立簡報時,你必須遵循以下結構:
- 投影片 1:封面頁
- 投影片 2:目錄(議程)
- 投影片 3 起:內容區段,嚴格按照投影片 2 所列的順序
- 最後一張投影片:結尾/感謝頁
不要跳過目錄投影片。不要將內容投影片放在目錄之前。
⚠️ 禁止空白投影片
每個投影片都必須包含至少一個可見元素(addText、addShape、addImage、addChart 或 addTable)在投影片內部。只有背景顏色而無內容元素的投影片是生成缺陷。
空白投影片的常見原因:
- 忘記為區段分隔頁/轉場投影片加入內容
- Token 截斷導致部分投影片在生成過程中變成空白
- 假設投影片版面配置或母版會自動填入內容(它們不會——pptxgenjs 會建立最小的版面配置,沒有繼承的圖形)
如果你打算將投影片作為區段分隔頁,你必須明確加入元素——例如,一個大的區段編號、標題文字和/或裝飾形狀。
⚠️ 必要:生成前規劃
在撰寫任何程式碼之前,你必須完成以下規劃步驟:
⚡ 簡短請求的快速路徑: 當使用者要求一個短/簡單的簡報(≤ 6 頁,單一主題,無複雜圖表)時,跳過正式的規劃輸出,直接進入步驟 3(撰寫程式碼),使用標準的「封面 + 目錄 + (N-3) 內容 + 結尾」結構。快速路徑 = 在你的回覆主體中不要有詳細的規劃內容,直接建立並執行腳本。
步驟 1:輸出內容設計計畫
提出一個結構化的計畫,涵蓋:
-
整體主題與樣式
- 調色板選擇(參考「設計想法」章節)
- 字型搭配
- 跨投影片使用的視覺主軸
-
逐投影片大綱
投影片 1:封面 - 版面類型,關鍵元素 投影片 2:目錄 - 有序的區段清單 投影片 3:[來自目錄的區段 1] - 版面類型,關鍵元素,視覺洞察計畫(如有) ... 投影片 N:結尾 / 感謝 - 版面類型,關鍵元素 ... -
視覺元素清單
- 列出所有需要的圖片、圖示、圖表與圖解
- 將每個標記為:
[內建](pptxgenjs 形狀/圖表)或[外部](需要預先產生)
規劃輸出範例:
## 簡報計畫
**主題:** Ocean Gradient 調色板 (065A82, 1C7293, 21295C)
**字型:** Georgia(標題)+ Calibri(內文)
**主軸:** 帶左側強調邊框的圓角卡片
### 投影片:
1. 封面投影片 - 置中標題,漸層背景
2. 目錄 - 概觀 / 架構 / 指標 / 時間線
3. [來自目錄的區段 1] - 版面類型,關鍵元素,視覺洞察計畫(如有)
...
n. 感謝 - 結尾語句 + 聯絡資訊
⚠️ 輸出你的計畫後,立即進行步驟 2 與步驟 3。不要重新規劃,不要用微小的變化重複相同的綱要。只輸出計畫一次,然後開始撰寫 pptxgenjs 程式碼。
步驟 2:預先產生外部素材
對於標記為 [外部] 的圖形,在撰寫 pptxgenjs 程式碼之前就產生它們。
⚠️ 重要:顏色一致性
所有產生的圖表與圖解都必須使用與簡報相同的調色板。根據你選擇的主題,在你的產生腳本頂部定義顏色。
選項 A:首先使用原生圖形/圖表(預設必要)
所有架構圖、流程圖、程序圖、組織圖與關係圖都必須使用 pptxgenjs 原生圖形(RECTANGLE、OVAL、LINE、連接器 + addText)來建立。請參閱 pptxgenjs.md 中的「使用原生圖形建立圖解」以了解模式與範例。
- 當適合時,使用強大的範本投影片(流程、比較、雙欄、圖示網格)
- 對於流程、架構與階層,使用 pptxgenjs 原生圖形(方框/箭頭/線條 + 文字)
- 對於簡單的資料圖表(長條圖、圓餅圖、折線圖等),使用 pptxgenjs 圖表
僅在 pptxgenjs 圖表無法處理複雜的統計圖表(熱力圖、散佈圖、盒鬚圖)時,才退回使用 matplotlib。 僅在圖解對於原生圖形來說過於複雜且涉及許多交叉連結時,才退回使用 Mermaid。
選項 B:Matplotlib/Python 圖表
在開始時定義調色板,以符合你的 PPT 主題:
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
# ============================================================
# 調色板 - 符合你的 PPT 主題
# ============================================================
# 範例:「Ocean Gradient」主題
COLORS = {
'primary': '#065A82',
'secondary': '#1C7293',
'accent': '#21295C',
'background': '#F0F7FA',
'text': '#21295C',
'light': '#E8F4F8',
}
# 多資料系列的顏色循環
COLOR_CYCLE = [COLORS['primary'], COLORS['secondary'], COLORS['accent'], '#4A90A4', '#2D5A6B']
# 全域套用主題
plt.rcParams.update({
'axes.prop_cycle': plt.cycler(color=COLOR_CYCLE),
'axes.facecolor': 'none',
'axes.edgecolor': COLORS['text'],
'axes.labelcolor': COLORS['text'],
'text.color': COLORS['text'],
'xtick.color': COLORS['text'],
'ytick.color': COLORS['text'],
'figure.facecolor': 'none',
'font.family': 'sans-serif',
'font.size': 12,
})
# ============================================================
# 使用主題顏色建立圖表
fig, ax = plt.subplots(figsize=(8, 5), dpi=150)
bars = ax.bar(['Q1', 'Q2', 'Q3', 'Q4'], [25, 40, 35, 50],
color=[COLORS['primary'], COLORS['secondary'], COLORS['primary'], COLORS['secondary']],
edgecolor=COLORS['accent'], linewidth=1.5)
ax.set_title('季度營收', fontsize=16, fontweight='bold', color=COLORS['text'])
ax.set_ylabel('營收 ($M)', color=COLORS['text'])
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
plt.tight_layout()
width_px, height_px = int(8 * 150), int(5 * 150)
plt.savefig(f'chart_{width_px}x{height_px}.png', dpi=150, transparent=True)
plt.close()
Matplotlib 調色板範本:
# 午夜藍調
COLORS = {'primary': '#1E2761', 'secondary': '#CADCFC', 'accent': '#FFFFFF', 'text': '#1E2761'}
# 森林與苔蘚
COLORS = {'primary': '#2C5F2D', 'secondary': '#97BC62', 'accent': '#F5F5F5', 'text': '#2C5F2D'}
# 珊瑚活力
COLORS = {'primary': '#F96167', 'secondary': '#F9E795', 'accent': '#2F3C7E', 'text': '#2F3C7E'}
# 溫暖赤陶
COLORS = {'primary': '#B85042', 'secondary': '#E7E8D1', 'accent': '#A7BEAE', 'text': '#B85042'}
# 青綠信賴
COLORS = {'primary': '#028090', 'secondary': '#00A896', 'accent': '#02C39A', 'text': '#028090'}
用於:
- 複雜的統計圖表(長條圖、折線圖、圓餅圖、散佈圖、雷達圖等)
- pptxgenjs 不支援的自訂視覺化
- 熱力圖、散佈圖、盒鬚圖
⚠️ 不要將 matplotlib 用於:
- 架構圖
- 流程圖 / 程序圖
- 組織圖 / 階層圖
- 網路拓撲圖
- 任何主要顯示元件之間關係的圖解
這些必須使用 pptxgenjs 原生圖形來建立,以便它們呈現為可編輯的 PPT 物件——而非點陣圖像。
Matplotlib - 支援中文的圖表
在使用 matplotlib 建立包含中文文字的圖表時,你必須設定字型:
import os
import platform
import matplotlib.pyplot as plt
import matplotlib
def setup_matplotlib_cjk():
"""設定 matplotlib 以支援中日韓 (CJK) 字元"""
system = platform.system()
if system == "Darwin": # macOS
font_names = ['Arial Unicode MS', 'PingFang SC', 'Heiti SC', 'STHeiti']
elif system == "Windows":
font_names = ['Microsoft YaHei', 'SimHei', 'SimSun']
else: # Linux
font_names = ['Noto Sans CJK SC', 'WenQuanYi Zen Hei', 'Droid Sans Fallback']
# 尋找可用的字型
available_fonts = [f.name for f in matplotlib.font_manager.fontManager.ttflist]
for font_name in font_names:
if font_name in available_fonts:
plt.rcParams['font.sans-serif'] = [font_name] + plt.rcParams['font.sans-serif']
plt.rcParams['axes.unicode_minus'] = False # 修正負號顯示
return font_name
return None
# 在建立圖表前設定 CJK 字型
cjk_font = setup_matplotlib_cjk()
# 建立一個帶有中文標籤的長條圖
categories = ['第一季度', '第二季度', '第三季度', '第四季度']
values = [120, 135, 142, 158]
plt.figure(figsize=(10, 6))
plt.bar(categories, values, color='steelblue')
plt.title('季度銷售數據 Quarterly Sales', fontsize=16)
plt.xlabel('季度 Quarter', fontsize=12)
plt.ylabel('銷售額 Sales', fontsize=12)
plt.tight_layout()
plt.savefig('chart.png', dpi=150)
plt.close()
選項 C:網路搜尋圖片
在以下情況搜尋相關圖片:
- 需要圖庫照片或插圖
- 需要圖示或標誌
- 需要概念的參考圖片
選項 D:Mermaid 圖解(最後手段)
僅在圖解無法以原生圖形/版面配置乾淨呈現時使用,並保持與簡報的一致性:
# 如需要則安裝:npm install -g @mermaid-js/mermaid-cli
建立一個符合你 PPT 調色板的主題設定檔:
// mermaid-config.json - 「Ocean Gradient」主題範例
{
"theme": "base",
"themeVariables": {
"primaryColor": "#065A82",
"primaryTextColor": "#FFFFFF",
"primaryBorderColor": "#21295C",
"secondaryColor": "#1C7293",
"secondaryTextColor": "#FFFFFF",
"secondaryBorderColor": "#065A82",
"tertiaryColor": "#E8F4F8",
"tertiaryTextColor": "#21295C",
"lineColor": "#21295C",
"textColor": "#21295C",
"mainBkg": "#E8F4F8",
"nodeBorder": "#065A82",
"clusterBkg": "#F0F7FA",
"titleColor": "#21295C",
"edgeLabelBackground": "#FFFFFF"
}
}
cat > diagram.mmd << 'EOF'
graph LR
A[客戶端] --> B[API 閘道器]
B --> C[服務 A]
B --> D[服務 B]
EOF
# 為了 PPT 使用,偏好高解析度匯出
mmdc -i diagram.mmd -o diagram.png -c mermaid-config.json -b white -w 1600 --scale 2
步驟 3:圖片命名慣例(必要)
所有產生的圖片都必須在檔名中包含尺寸:
{名稱}_{寬度}x{高度}.png
範例:
architecture_800x600.png- 800px 寬,600px 高timeline_1200x400.png- 1200px 寬,400px 高chart_600x600.png- 600px 方形
儲存圖片時,務必包含尺寸:
# Matplotlib 範例
fig, ax = plt.subplots(figsize=(8, 5), dpi=150)
# ... 建立圖表 ...
width_px = int(8 * 150) # 1200
height_px = int(5 * 150) # 750
plt.savefig(f'chart_{width_px}x{height_px}.png', dpi=150, transparent=True)
# 通用