powerpoint

作者: microsoft

使用 python-pptx 並透過 YAML 驅動內容與樣式來生成和管理 PowerPoint 投影片組 - 由 microsoft/hve-core 提供

npx skills add https://github.com/microsoft/hve-core --skill powerpoint

PowerPoint Skill

Generates, updates, and manages PowerPoint slide decks using python-pptx with YAML-driven content and styling definitions.

Overview

This skill provides Python scripts that consume YAML configuration files to produce PowerPoint slide decks. Each slide is defined by a content.yaml file describing its layout, text, and shapes. A style.yaml file defines dimensions, template configuration, layout mappings, metadata, and defaults.

SKILL.md covers technical reference: prerequisites, commands, script architecture, API constraints, and troubleshooting. For conventions and design rules (element positioning, visual quality, color and contrast, contextual styling), follow pptx.instructions.md.

Prerequisites

PowerShell

The Invoke-PptxPipeline.ps1 script handles virtual environment creation and dependency installation automatically via uv sync. Requires uv, Python 3.11+, and PowerShell 7+.

Installing uv

If uv is not installed:

# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh

# Windows
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

# Via pip (fallback)
pip install uv

System Dependencies (Export and Validation)

The Export and Validate actions require LibreOffice for PPTX-to-PDF conversion and optionally pdftoppm from poppler for PDF-to-JPG rendering. When pdftoppm is not available, PyMuPDF handles the image rendering.

The Validate action's vision-based checks require the GitHub Copilot CLI for model access.

# macOS
brew install --cask libreoffice
brew install poppler        # optional, provides pdftoppm

# Linux
sudo apt-get install libreoffice poppler-utils

# Windows (winget preferred, choco fallback)
winget install TheDocumentFoundation.LibreOffice
# choco install libreoffice-still      # alternative
# poppler: no winget package; use choco install poppler (optional, provides pdftoppm)

Copilot CLI (Vision Validation)

The validate_slides.py script uses the GitHub Copilot SDK to send slide images to vision-capable models. The Copilot CLI must be installed and authenticated:

# Install Copilot CLI
npm install -g @github/copilot-cli

# Authenticate (uses the same GitHub account as VS Code Copilot)
copilot auth login

# Verify
copilot --version

Required Files

  • style.yaml — Dimensions, defaults, template configuration, and metadata
  • content.yaml — Per-slide content definition (text, shapes, images, layout)
  • (Optional) content-extra.py — Custom Python for complex slide drawings

Content Directory Structure

All slide content lives under the working directory's content/ folder:

content/
├── global/
│   ├── style.yaml              # Dimensions, defaults, template config, and theme metadata
│   └── voice-guide.md          # Voice and tone guidelines
├── slide-001/
│   ├── content.yaml            # Slide 1 content and layout
│   └── images/                 # Slide-specific images
│       ├── background.png
│       └── background.yaml     # Image metadata sidecar
├── slide-002/
│   ├── content.yaml            # Slide 2 content and layout
│   ├── content-extra.py        # Custom Python for complex drawings
│   └── images/
│       └── screenshot.png
├── slide-003/
│   ├── content.yaml
│   └── images/
│       ├── diagram.png
│       └── diagram.yaml
└── ...

Global Style Definition (style.yaml)

The global style.yaml defines dimensions, template configuration, layout mappings, metadata, and defaults. Color and font choices are specified per-element in each slide's content.yaml rather than centralized in the style file.

See the style.yaml template for the full template, field reference, and usage instructions.

Per-Slide Content Definition (content.yaml)

Each slide's content.yaml defines layout, text, shapes, and positioning. All position and size values are in inches. Color values use #RRGGBB hex format or @theme_name references.

Text contract: markdown-like list lines in textbox.text and shape.text are interpreted as PowerPoint lists during rendering. Unordered markers (-, +, *) become bulleted paragraphs, ordered markers (1., 1)) become auto-numbered paragraphs, and leading indentation maps to paragraph level.

See the content.yaml template for the full template, supported element types, supported shape types, and usage instructions.

Complex Drawings (content-extra.py)

When a slide requires complex drawings that cannot be expressed through content.yaml element definitions, create a content-extra.py file in the slide folder. The render() function signature is fixed. The build script calls it after placing standard content.yaml elements.

See the content-extra.py template for the full template, function parameters, and usage guidelines.

Security Validation

content-extra.py execution is disabled by default. When a slide folder contains one and --allow-scripts is not passed, the build fails with an error naming the file. Pass --allow-scripts to authorize execution after reviewing the script.

When execution is authorized, the build script performs AST-based static analysis before running the file and rejects the patterns below. This analysis is a lint that catches obvious mistakes early. It is not a security boundary: a blocked module reached through an alias is not detected, and pathlib and open are permitted. Authorization is the control.

Allowed imports:

  • pptx and all pptx.* submodules
  • Safe standard-library modules (e.g., math, copy, json, re, pathlib, collections, itertools, functools, typing, enum, dataclasses, decimal, fractions, string, textwrap)

Blocked imports:

  • subprocess, os, shutil, socket, ctypes, signal, multiprocessing, threading, http, urllib, ftplib, smtplib, imaplib, poplib, xmlrpc, webbrowser, code, codeop, compileall, py_compile, zipimport, pkgutil, runpy, ensurepip, venv, sqlite3, tempfile, shelve, dbm, pickle, marshal, importlib, sys, telnetlib
  • Any third-party package not on the allowlist

Blocked builtins:

  • Dangerous: eval, exec, __import__, compile, breakpoint
  • Indirect bypass: getattr, setattr, delattr, globals, locals, vars
  • Attribute-form calls onto builtins, os, sys, subprocess, and importlib (for example builtins.eval(...))

--allow-scripts flag:

Pass --allow-scripts to authorize execution of content-extra.py files. Without it, a present script fails the build rather than being skipped, so a deck never silently loses custom drawings. The flag authorizes execution; it does not skip the lint.

This is a behavior change. A deck that previously built with a content-extra.py present now requires --allow-scripts, and a script relying on a blocked import no longer has a bypass.

python scripts/build_deck.py \
  --content-dir content/ \
  --style content/global/style.yaml \
  --output slide-deck/presentation.pptx \
  --allow-scripts

When validation fails, the build raises ContentExtraError with a message identifying the violation and file path.

Script Reference

The full command surface lives in references/script-reference.md: build a deck, build from a template, update specific slides, extract content from an existing PPTX, validate, export slides to images or SVG, dry-run validation, generate theme variants, and embed audio.

Script Architecture

The build and extraction scripts use shared modules in the scripts/ directory:

ModulePurpose
pptx_utils.pyShared utilities: exit codes, logging configuration, slide filter parsing, unit conversion (emu_to_inches()), YAML loading
pptx_colors.pyColor resolution (#hex, @theme, dict with brightness), theme color map (16 entries)
pptx_fonts.pyFont resolution, family normalization, weight suffix handling, alignment mapping
pptx_shapes.pyShape constant map (29 entries + circle alias), auto-shape name mapping, rotation utilities
pptx_fills.pySolid, gradient, and pattern fill application/extraction; line/border styling with dash styles
pptx_text.pyText frame properties (margins, auto-size, vertical anchor), paragraph properties (spacing, level), run properties (underline, hyperlink), markdown-like list parsing to bullet/auto-number paragraphs
pptx_tables.pyTable element creation and extraction with cell merging, banding, and per-cell styling
pptx_charts.pyChart element creation and extraction for 12 chart types (column, bar, line, pie, scatter, bubble, etc.)
validate_deck.pyPPTX-only validation for speaker notes and slide count
validate_geometry.pyStructural validation for element edge margins, adjacent gaps, boundary overflow, and title clearance
validate_slides.pyVision-based slide issue detection and quality validation via Copilot SDK with built-in checks and plain-text per-slide output
render_pdf_images.pyPDF-to-JPG rendering via PyMuPDF with optional slide-number-based naming
generate_themes.pyTheme variant generation from a base content directory using a color mapping YAML file
embed_audio.pyWAV audio embedding into PPTX slides with per-slide file matching and off-screen audio icon placement
export_svg.pyPPTX-to-SVG export via LibreOffice PDF conversion and PyMuPDF SVG rendering

python-pptx Constraints

  • python-pptx does NOT support SVG images. Always convert to PNG via cairosvg or Pillow.
  • python-pptx cannot create new slide masters or layouts programmatically. Use blank layouts or start from a template PPTX with the --template argument.
  • Transitions and animations are preserved when opening and saving existing files, but cannot be created or modified via the API.
  • When extracting content, slide master and layout inheritance means many text elements have no inline styling. Add explicit font properties in content YAML before rebuilding.
  • The Export and Validate actions require LibreOffice for PPTX-to-PDF conversion. The PowerShell orchestrator checks for LibreOffice availability before starting and provides platform-specific install instructions if missing.
  • Accessing background.fill on slides with inherited backgrounds replaces them with NoFill. Check slide.follow_master_background before accessing the fill property.
  • Gradient fills use the python-pptx GradientFill API with GradientStop objects. Each stop specifies a position (0–100) and a color.
  • Theme colors resolve via MSO_THEME_COLOR enum. Brightness adjustments apply through the color format's brightness property.
  • Template-based builds load layouts by name or index. Layout name resolution falls back to index 6 (blank) when no match is found.

Security Considerations

This skill processes PDF files via PyMuPDF, which wraps the MuPDF C library. MuPDF parses untrusted binary structures (cross-reference tables, stream objects, font definitions) and historical CVEs have shown that memory-safety bugs in C parsers can lead to crashes, memory disclosure, or in rare cases code execution.

Mitigations in place

  • scripts/pdf_safety.py validates every PDF (existence, regular-file, size <= 100 MB, %PDF- magic bytes, page count <= 1000) before calling fitz.open().
  • All fitz operations are wrapped in safe_open_pdf(), which converts MuPDF exceptions into typed PdfSafetyError subclasses (PdfTooLargeError, PdfInvalidFormatError, PdfTooManyPagesError, PdfParseError, PdfRenderError).
  • pymupdf is version-pinned in pyproject.toml (>=1.27.1,<2.0) to track security fixes without silently adopting a major-version API change.

Defense-in-depth note: the 5-byte %PDF- magic check is a necessary but not sufficient guarantee of structural validity. A crafted small file that begins with %PDF- still reaches the MuPDF parser, where memory-safety bugs may exist. Callers MUST keep PyMuPDF patched against the latest advisories (tracked via microsoft/hve-core#1020 / pip-audit) and continue to treat such inputs as untrusted. The PdfSafetyError hierarchy (PdfTooLargeError, PdfInvalidFormatError, PdfTooManyPagesError, PdfParseError, PdfRenderError) is one defense layer alongside the version pin and CVE monitoring; no single layer is sufficient on its own.

Accepted risk

These mitigations reduce but do not eliminate the C-extension attack surface. Consumers SHOULD treat PDF inputs from outside this skill's PPTX-to-PDF pipeline as untrusted and apply additional sandboxing (subprocess, container) before feeding adversarial input.

Update policy

Re-check NVD and OSV advisories for MuPDF and PyMuPDF quarterly and on every pip-audit alert.

Cross-references

  • microsoft/hve-core#1018 — original hardening request
  • microsoft/hve-core#1020 — pip-audit CI for ongoing CVE monitoring (separate effort)

Troubleshooting

IssueCauseSolution
SVG runtime errorpython-pptx cannot embed SVGConvert to PNG via cairosvg before adding
Text overlay between elementsInsufficient vertical spacingFollow element positioning conventions in pptx.instructions.md
Width overflow off-slideElement extends beyond slide boundaryFollow element positioning conventions in pptx.instructions.md
Bright accent color unreadable as fillWhite text on bright backgroundDarken accent to ~60% saturation for box fills
Background fill replaced with NoFillAccessed background.fill on inherited backgroundCheck slide.follow_master_background before accessing
Missing speaker notesNotes not specified in content.yamlAdd speaker_notes field to every content slide
LibreOffice not found during ValidateValidate exports slides to images firstInstall LibreOffice: brew install --cask libreoffice (macOS)
uv not founduv package manager not installedInstall uv: curl -LsSf https://astral.sh/uv/install.sh | sh (macOS/Linux) or pip install uv
Python not found by uvNo Python 3.11+ on PATHInstall via uv python install 3.11 or pyenv install 3.11
uv sync failsMissing or corrupt .venvDelete .venv/ at the skill root and re-run uv sync
Import errors in scriptsDependencies not installed or stale venvRun uv sync from the skill root to recreate the environment

Environment Recovery

When scripts fail due to missing modules, import errors, or a corrupt virtual environment, recover with:

cd "<powerpoint-skill-root>"
rm -rf .venv
uv sync

Resolve <powerpoint-skill-root> from the loaded skill location before running the command.

This recreates the virtual environment from scratch using pyproject.toml as the single source of truth. The Invoke-PptxPipeline.ps1 orchestrator runs uv sync automatically on each invocation unless -SkipVenvSetup is passed.

When uv itself is not available, install it first (see Installing uv above), then retry. When Python 3.11+ is not available, run uv python install 3.11 to have uv fetch and manage the interpreter.

來自 microsoft 的更多技能

oss-growth
microsoft
開源增長駭客角色
agent-framework-azure-ai-py
microsoft
使用Microsoft Agent Framework Python SDK(agent-framework-azure-ai)构建Azure AI Foundry代理。适用于使用AzureAIAgentsProvider创建持久化代理、使用托管工具(代码解释器、文件搜索、网络搜索)、集成MCP服务器、管理对话线程或实现流式响应。涵盖函数工具、结构化输出和多工具代理。
development
airunway-aks-setup
microsoft
在AKS上設定AI Runway——從裸叢集到執行模型。涵蓋叢集驗證、控制器安裝、GPU評估、供應商設定及首次部署。時機:「設定AI Runway」、「上線AKS叢集」、「安裝AI Runway」、「airunway設定」、「部署模型至AKS」、「在AKS上進行GPU推論」、「在AKS上設定KAITO」、「在AKS上執行LLM」、「在AKS上使用vLLM」、「在AKS上設定模型服務」、「AI Runway控制器」。
devops
appinsights-instrumentation
microsoft
使用Azure Application Insights檢測Web應用程式的指南。提供遙測模式、SDK設定與組態參考。適用時機:如何檢測應用程式、App Insights SDK、遙測模式、什麼是App Insights、Application Insights指南、檢測範例、APM最佳實踐。
devops
applicationinsights-web-ts
microsoft
使用Application Insights JavaScript SDK(@microsoft/applicationinsights-web)為瀏覽器/Web應用程式進行檢測。適用於真實使用者監控(RUM)——頁面檢視、點擊、AJAX/fetch依賴、例外、自訂事件,以及與後端OpenTelemetry追蹤關聯的瀏覽器端GenAI代理追蹤。涵蓋SDK載入器指令碼與npm設定、框架擴充(React、React Native、Angular)、點擊分析、遙測初始化器,以及從瀏覽器發出的代理/工具/模型span的OTel GenAI語意慣例。
devops
azure-ai-anomalydetector-java
microsoft
使用適用於 Java 的 Azure AI 異常偵測器 SDK 建置異常偵測應用程式。在實作單變量/多變量異常偵測、時間序列分析或 AI 驅動監控時使用。
development
azure-ai-language-conversations-py
microsoft
使用 azure-ai-language-conversations Python SDK 實作對話語言理解(CLU)。當使用 ConversationAnalysisClient 分析對話意圖與實體、建置 NLP 功能,或將語言理解整合至應用程式時使用。
development
azure-ai-ml-py
microsoft
Azure Machine Learning SDK v2 for Python。用於機器學習工作區、作業、模型、資料集、計算資源與管線。 觸發詞:「azure-ai-ml」、「MLClient」、「workspace」、「model registry」、「training jobs」、「datasets」。
development