single-slide-ppt
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSingle-Slide PowerPoint Creator
单页PowerPoint生成工具
Create professional, visually engaging single-slide PowerPoint presentations using PptxGenJS.
使用PptxGenJS创建专业、视觉吸引力强的单页PowerPoint演示文稿。
When to Use This Skill
使用场景
- User requests "做一页PPT", "single slide", "create a PPT slide"
- Visualizing comparisons (before/after, old vs new, problem/solution)
- Feature showcases (grid layouts, capability matrices)
- Concept illustrations (workflows, architectures, frameworks)
- Decision frameworks or process flows
- 用户请求「做一页PPT」「single slide」「create a PPT slide」
- 可视化对比内容(前后对比、新旧对比、问题/解决方案)
- 功能展示(网格布局、能力矩阵)
- 概念示意图(工作流、架构、框架)
- 决策框架或流程步骤
Core Workflow
核心工作流
1. Understand Content Structure
1. 分析内容结构
Analyze the user's request to identify:
- Main message/title
- Key points or sections (typically 2-6 items)
- Natural groupings (left/right, grid, sequential)
- Visual metaphors (arrows, icons, cards)
分析用户需求,确定:
- 核心信息/标题
- 关键点或板块(通常2-6个)
- 自然分组方式(左右分栏、网格、顺序排列)
- 视觉隐喻(箭头、图标、卡片)
2. Choose Design Pattern
2. 选择设计模式
Select a layout that matches the content structure:
Comparison Layouts (2 columns):
- Problem → Solution
- Before → After
- Old → New
- Plugin → IDE
Grid Layouts (2x2, 2x3, 3x3):
- Feature showcase
- Capability matrix
- Multi-option comparison
Sequential Flow:
- Process steps
- Timeline
- Decision tree
Single Focus:
- Key metric
- Core concept
- Quote or statement
根据内容结构选择合适的布局:
对比布局(双列):
- 问题 → 解决方案
- 之前 → 之后
- 旧版 → 新版
- 插件 → IDE
网格布局(2x2、2x3、3x3):
- 功能展示
- 能力矩阵
- 多选项对比
顺序流布局:
- 流程步骤
- 时间线
- 决策树
单焦点布局:
- 关键指标
- 核心概念
- 引用或声明
3. Design Color Palette
3. 设计配色方案
Select 3-5 colors based on content theme:
Content-driven palettes:
- Technology: Deep blue (#1a1a2e), purple (#4a00e0), accent (#8e2de2)
- Problem/Solution: Red (#ff6b6b) for problems, Green (#51cf66) for solutions
- Professional: Navy (#2C3E50), teal (#16A085), gold (#F39C12)
- Creative: Purple (#722880), pink (#D72D51), orange (#EB5C18)
Color assignment:
- Background: Dark (#1a1a2e) or light (#f5f5f5)
- Header: Primary brand color or gradient
- Problem/negative: Red/orange tones
- Solution/positive: Green/blue tones
- Accent: Complementary color for highlights
根据内容主题选择3-5种颜色:
基于内容的配色方案:
- 科技主题:深蓝(#1a1a2e)、紫色(#4a00e0)、强调色(#8e2de2)
- 问题/解决方案主题:红色(#ff6b6b)代表问题,绿色(#51cf66)代表解决方案
- 专业商务主题:藏蓝(#2C3E50)、蓝绿色(#16A085)、金色(#F39C12)
- 创意主题:紫色(#722880)、粉色(#D72D51)、橙色(#EB5C18)
颜色分配规则:
- 背景:深色(#1a1a2e)或浅色(#f5f5f5)
- 标题栏:主品牌色或渐变色
- 问题/负面内容:红/橙色调
- 解决方案/正面内容:绿/蓝色调
- 强调色:互补色用于突出重点
4. Enhance with Relevant Images (Optional)
4. 添加相关图片(可选)
When creating slides about technical concepts, products, or comparisons, consider adding relevant images to strengthen the message.
When to use images:
- Technical architecture diagrams (from official documentation)
- Product screenshots (before/after comparisons)
- Logo or brand assets (for product slides)
- Illustrations (to explain abstract concepts)
- Charts or graphs (data visualization)
How to find and download images:
javascript
// Example: Download VSCode architecture diagram
// Use curl to download images from official sources
const { execSync } = require('child_process');
function downloadImage(url, outputPath) {
try {
execSync(`curl -o ${outputPath} "${url}"`, { stdio: 'inherit' });
console.log(`Downloaded: ${outputPath}`);
return true;
} catch (error) {
console.error(`Failed to download image: ${error.message}`);
return false;
}
}
// Example usage:
downloadImage(
'https://code.visualstudio.com/assets/api/ux-guidelines/examples/architecture-containers.png',
'workspace/vscode-architecture.png'
);Strategy for finding images:
- Official documentation: Search for "[Product Name] architecture documentation" or "[Product Name] official API documentation"
- GitHub repositories: Look for diagrams in README.md or docs/ folders
- Technical blogs: Find explanation diagrams from reputable sources
- Use search_web and fetch_web: Search for relevant content and extract image URLs
Adding images to slides:
javascript
// After downloading the image, add it to the slide
slide.addImage({
path: 'workspace/downloaded-image.png',
x: 0.5, // X position in inches
y: 1.5, // Y position in inches
w: 4.8, // Width in inches
h: 2.7 // Height in inches (maintain aspect ratio)
});
// Optional: Add caption
slide.addText('Image caption or source attribution', {
x: 0.5, y: 4.25, w: 4.8, h: 0.3,
fontSize: 9, color: '707070', italic: true,
align: 'center'
});Best practices for images:
- ✅ Use official sources (company websites, documentation)
- ✅ Maintain aspect ratio when resizing
- ✅ Add captions for context
- ✅ Ensure images support the narrative
- ❌ Don't use low-resolution images
- ❌ Don't overcrowd slides with too many images
- ❌ Don't use images without permission
当制作技术概念、产品或对比类幻灯片时,可添加相关图片增强表达效果。
适合添加图片的场景:
- 技术架构图(来自官方文档)
- 产品截图(前后对比)
- Logo或品牌资产(产品类幻灯片)
- 示意图(解释抽象概念)
- 图表或图形(数据可视化)
图片查找与下载方法:
javascript
// Example: Download VSCode architecture diagram
// Use curl to download images from official sources
const { execSync } = require('child_process');
function downloadImage(url, outputPath) {
try {
execSync(`curl -o ${outputPath} "${url}"`, { stdio: 'inherit' });
console.log(`Downloaded: ${outputPath}`);
return true;
} catch (error) {
console.error(`Failed to download image: ${error.message}`);
return false;
}
}
// Example usage:
downloadImage(
'https://code.visualstudio.com/assets/api/ux-guidelines/examples/architecture-containers.png',
'workspace/vscode-architecture.png'
);图片查找策略:
- 官方文档:搜索「[产品名称] 架构文档」或「[产品名称] 官方API文档」
- GitHub仓库:查看README.md或docs/文件夹中的图表
- 技术博客:从权威来源查找解释性图表
- 使用搜索工具:搜索相关内容并提取图片URL
向幻灯片添加图片:
javascript
// After downloading the image, add it to the slide
slide.addImage({
path: 'workspace/downloaded-image.png',
x: 0.5, // X position in inches
y: 1.5, // Y position in inches
w: 4.8, // Width in inches
h: 2.7 // Height in inches (maintain aspect ratio)
});
// Optional: Add caption
slide.addText('Image caption or source attribution', {
x: 0.5, y: 4.25, w: 4.8, h: 0.3,
fontSize: 9, color: '707070', italic: true,
align: 'center'
});图片使用最佳实践:
- ✅ 使用官方来源(公司网站、文档)
- ✅ 调整大小时保持宽高比
- ✅ 添加说明提供上下文
- ✅ 确保图片支持核心叙事
- ❌ 不使用低分辨率图片
- ❌ 不使用过多图片导致幻灯片拥挤
- ❌ 不使用未经授权的图片
5. Create Slide with PptxGenJS
5. 使用PptxGenJS创建幻灯片
javascript
const pptxgen = require('pptxgenjs');
const { execSync } = require('child_process');
const path = require('path');
async function createSlide() {
const pptx = new pptxgen();
pptx.layout = 'LAYOUT_16x9';
pptx.author = 'Your Name';
pptx.title = 'Slide Title';
const slide = pptx.addSlide();
// Background
slide.background = { color: '1a1a2e' };
// Header bar
slide.addShape(pptx.shapes.RECTANGLE, {
x: 0, y: 0, w: 10, h: 0.8,
fill: { color: '4a00e0' }
});
// Title
slide.addText('Your Title Here', {
x: 0.5, y: 0.18, w: 9, h: 0.5,
fontSize: 26, bold: true, color: 'ffffff',
fontFace: 'Arial'
});
// Optional: Add downloaded image
// slide.addImage({
// path: 'workspace/image.png',
// x: 0.5, y: 1.5, w: 4.8, h: 2.7
// });
// Content sections...
// [Add your content here following the patterns below]
await pptx.writeFile({ fileName: 'output.pptx' });
}
createSlide().catch(console.error);javascript
const pptxgen = require('pptxgenjs');
const { execSync } = require('child_process');
const path = require('path');
async function createSlide() {
const pptx = new pptxgen();
pptx.layout = 'LAYOUT_16x9';
pptx.author = 'Your Name';
pptx.title = 'Slide Title';
const slide = pptx.addSlide();
// Background
slide.background = { color: '1a1a2e' };
// Header bar
slide.addShape(pptx.shapes.RECTANGLE, {
x: 0, y: 0, w: 10, h: 0.8,
fill: { color: '4a00e0' }
});
// Title
slide.addText('Your Title Here', {
x: 0.5, y: 0.18, w: 9, h: 0.5,
fontSize: 26, bold: true, color: 'ffffff',
fontFace: 'Arial'
});
// Optional: Add downloaded image
// slide.addImage({
// path: 'workspace/image.png',
// x: 0.5, y: 1.5, w: 4.8, h: 2.7
// });
// Content sections...
// [Add your content here following the patterns below]
await pptx.writeFile({ fileName: 'output.pptx' });
}
createSlide().catch(console.error);Design Patterns Library
设计模式库
Pattern: Comparison Cards (Left vs Right)
模式:对比卡片(左右分栏)
javascript
// Left section - Problem/Before
slide.addText('🚫 Current State', {
x: 0.4, y: 1.0, w: 4, h: 0.4,
fontSize: 14, bold: true, color: 'ff6b6b'
});
// Card with left border accent
slide.addShape(pptx.shapes.RECTANGLE, {
x: 0.4, y: 1.5, w: 4.2, h: 0.95,
fill: { color: '2d1f1f' }
});
slide.addShape(pptx.shapes.RECTANGLE, {
x: 0.4, y: 1.5, w: 0.08, h: 0.95,
fill: { color: 'ff6b6b' }
});
slide.addText('Issue Title', {
x: 0.6, y: 1.55, w: 3.8, h: 0.3,
fontSize: 12, bold: true, color: 'ff6b6b'
});
slide.addText('Detailed description...', {
x: 0.6, y: 1.85, w: 3.8, h: 0.5,
fontSize: 9, color: 'a0a0a0', wrap: true
});
// Right section - Solution/After (mirror structure with green)
slide.addText('✅ New State', {
x: 5.3, y: 1.0, w: 4, h: 0.4,
fontSize: 14, bold: true, color: '51cf66'
});
// [Add cards using green color scheme]javascript
// Left section - Problem/Before
slide.addText('🚫 Current State', {
x: 0.4, y: 1.0, w: 4, h: 0.4,
fontSize: 14, bold: true, color: 'ff6b6b'
});
// Card with left border accent
slide.addShape(pptx.shapes.RECTANGLE, {
x: 0.4, y: 1.5, w: 4.2, h: 0.95,
fill: { color: '2d1f1f' }
});
slide.addShape(pptx.shapes.RECTANGLE, {
x: 0.4, y: 1.5, w: 0.08, h: 0.95,
fill: { color: 'ff6b6b' }
});
slide.addText('Issue Title', {
x: 0.6, y: 1.55, w: 3.8, h: 0.3,
fontSize: 12, bold: true, color: 'ff6b6b'
});
slide.addText('Detailed description...', {
x: 0.6, y: 1.85, w: 3.8, h: 0.5,
fontSize: 9, color: 'a0a0a0', wrap: true
});
// Right section - Solution/After (mirror structure with green)
slide.addText('✅ New State', {
x: 5.3, y: 1.0, w: 4, h: 0.4,
fontSize: 14, bold: true, color: '51cf66'
});
// [Add cards using green color scheme]Pattern: Feature Grid (2x3)
模式:功能网格(2x3)
javascript
const features = [
{ icon: '🔧', text: 'Feature 1' },
{ icon: '⚡', text: 'Feature 2' },
{ icon: '💻', text: 'Feature 3' },
{ icon: '📝', text: 'Feature 4' },
{ icon: '👻', text: 'Feature 5' },
{ icon: '🎨', text: 'Feature 6' }
];
const startX = 1.0;
const startY = 1.5;
const itemW = 2.6;
const itemH = 0.7;
const gapX = 0.15;
const gapY = 0.12;
features.forEach((feat, idx) => {
const col = idx % 3;
const row = Math.floor(idx / 3);
const x = startX + col * (itemW + gapX);
const y = startY + row * (itemH + gapY);
slide.addShape(pptx.shapes.ROUNDED_RECTANGLE, {
x, y, w: itemW, h: itemH,
fill: { color: '1a2a1a' },
line: { color: '51cf66', width: 0.5 },
rectRadius: 0.08
});
slide.addText(feat.icon + ' ' + feat.text, {
x: x + 0.1, y: y + 0.15, w: itemW - 0.2, h: itemH - 0.3,
fontSize: 11, color: 'e0e0e0', valign: 'middle'
});
});javascript
const features = [
{ icon: '🔧', text: 'Feature 1' },
{ icon: '⚡', text: 'Feature 2' },
{ icon: '💻', text: 'Feature 3' },
{ icon: '📝', text: 'Feature 4' },
{ icon: '👻', text: 'Feature 5' },
{ icon: '🎨', text: 'Feature 6' }
];
const startX = 1.0;
const startY = 1.5;
const itemW = 2.6;
const itemH = 0.7;
const gapX = 0.15;
const gapY = 0.12;
features.forEach((feat, idx) => {
const col = idx % 3;
const row = Math.floor(idx / 3);
const x = startX + col * (itemW + gapX);
const y = startY + row * (itemH + gapY);
slide.addShape(pptx.shapes.ROUNDED_RECTANGLE, {
x, y, w: itemW, h: itemH,
fill: { color: '1a2a1a' },
line: { color: '51cf66', width: 0.5 },
rectRadius: 0.08
});
slide.addText(feat.icon + ' ' + feat.text, {
x: x + 0.1, y: y + 0.15, w: itemW - 0.2, h: itemH - 0.3,
fontSize: 11, color: 'e0e0e0', valign: 'middle'
});
});Pattern: Visual Comparison Boxes
模式:视觉对比框
javascript
// Before box (dashed border)
slide.addShape(pptx.shapes.RECTANGLE, {
x: 1.5, y: 3.0, w: 2.5, h: 1.5,
fill: { color: '2a1a1a' },
line: { color: 'ff6b6b', width: 1, dashType: 'dash' }
});
slide.addText('Before', {
x: 1.5, y: 3.1, w: 2.5, h: 0.3,
fontSize: 12, bold: true, color: 'ff6b6b', align: 'center'
});
slide.addText('🧩', {
x: 1.5, y: 3.5, w: 2.5, h: 0.5,
fontSize: 32, align: 'center'
});
slide.addText('Old approach', {
x: 1.5, y: 4.0, w: 2.5, h: 0.3,
fontSize: 9, color: '888888', align: 'center'
});
// After box (solid border)
slide.addShape(pptx.shapes.RECTANGLE, {
x: 6.0, y: 3.0, w: 2.5, h: 1.5,
fill: { color: '1a2a1a' },
line: { color: '51cf66', width: 2 }
});
slide.addText('After', {
x: 6.0, y: 3.1, w: 2.5, h: 0.3,
fontSize: 12, bold: true, color: '51cf66', align: 'center'
});
slide.addText('👑', {
x: 6.0, y: 3.5, w: 2.5, h: 0.5,
fontSize: 32, align: 'center'
});
slide.addText('New approach', {
x: 6.0, y: 4.0, w: 2.5, h: 0.3,
fontSize: 9, color: '888888', align: 'center'
});javascript
// Before box (dashed border)
slide.addShape(pptx.shapes.RECTANGLE, {
x: 1.5, y: 3.0, w: 2.5, h: 1.5,
fill: { color: '2a1a1a' },
line: { color: 'ff6b6b', width: 1, dashType: 'dash' }
});
slide.addText('Before', {
x: 1.5, y: 3.1, w: 2.5, h: 0.3,
fontSize: 12, bold: true, color: 'ff6b6b', align: 'center'
});
slide.addText('🧩', {
x: 1.5, y: 3.5, w: 2.5, h: 0.5,
fontSize: 32, align: 'center'
});
slide.addText('Old approach', {
x: 1.5, y: 4.0, w: 2.5, h: 0.3,
fontSize: 9, color: '888888', align: 'center'
});
// After box (solid border)
slide.addShape(pptx.shapes.RECTANGLE, {
x: 6.0, y: 3.0, w: 2.5, h: 1.5,
fill: { color: '1a2a1a' },
line: { color: '51cf66', width: 2 }
});
slide.addText('After', {
x: 6.0, y: 3.1, w: 2.5, h: 0.3,
fontSize: 12, bold: true, color: '51cf66', align: 'center'
});
slide.addText('👑', {
x: 6.0, y: 3.5, w: 2.5, h: 0.5,
fontSize: 32, align: 'center'
});
slide.addText('New approach', {
x: 6.0, y: 4.0, w: 2.5, h: 0.3,
fontSize: 9, color: '888888', align: 'center'
});Pattern: Arrow Connector
模式:箭头连接器
javascript
// Arrow between sections
slide.addText('➔', {
x: 4.5, y: 2.5, w: 0.8, h: 0.6,
fontSize: 36, color: '8e2de2',
align: 'center', valign: 'middle'
});javascript
// Arrow between sections
slide.addText('➔', {
x: 4.5, y: 2.5, w: 0.8, h: 0.6,
fontSize: 36, color: '8e2de2',
align: 'center', valign: 'middle'
});Visual Design Best Practices
视觉设计最佳实践
Typography
排版
- Titles: 22-28pt, bold, high contrast
- Section headers: 12-16pt, bold
- Body text: 9-11pt, medium weight
- Captions: 8-9pt, lighter color
- 标题:22-28号字,加粗,高对比度
- 板块标题:12-16号字,加粗
- 正文:9-11号字,中等字重
- 说明文字:8-9号字,浅色调
Spacing & Alignment
间距与对齐
- Header height: 0.7-0.9 inches
- Section margins: 0.4-0.5 inches from edges
- Card padding: 0.1-0.15 inches internal
- Grid gaps: 0.08-0.15 inches
- 标题栏高度:0.7-0.9英寸
- 板块边距:距边缘0.4-0.5英寸
- 卡片内边距:0.1-0.15英寸
- 网格间距:0.08-0.15英寸
Color Usage
颜色使用
- Maximum 5 colors per slide
- Use transparency for layering: becomes
rgba(R,G,B,0.1)+ lighter fillRRGGBB - Ensure text contrast ratio > 4.5:1 (use #e0e0e0 text on dark backgrounds)
- 单页幻灯片最多使用5种颜色
- 使用透明度实现分层效果:对应浅色填充的
rgba(R,G,B,0.1)RRGGBB - 确保文本对比度>4.5:1(深色背景使用#e0e0e0文本)
Visual Hierarchy
视觉层级
- Title/header (largest, highest contrast)
- Section headers (medium, color-coded)
- Content cards (grouped, bordered)
- Supporting text (smallest, lower contrast)
- 标题/标题栏(字号最大,对比度最高)
- 板块标题(中等字号,颜色编码)
- 内容卡片(分组,带边框)
- 辅助文本(字号最小,对比度较低)
Common Slide Types
常见幻灯片类型
1. Problem → Solution Slide
1. 问题→解决方案幻灯片
- Left: Problem cards (red theme)
- Middle: Arrow connector
- Right: Solution features (green theme)
- Bottom: Core value proposition
- 左侧:问题卡片(红色主题)
- 中间:箭头连接器
- 右侧:解决方案功能(绿色主题)
- 底部:核心价值主张
2. Feature Showcase
2. 功能展示幻灯片
- Header with product name
- 2x3 or 3x3 grid of features
- Each cell: icon + short description
- Optional: Key benefit card at bottom
- 标题栏包含产品名称
- 2x3或3x3的功能网格
- 每个单元格:图标+简短描述
- 可选:底部添加核心优势卡片
3. Before/After Comparison
3. 前后对比幻灯片
- Title explaining transformation
- Side-by-side comparison boxes
- Visual indicators (emoji/icons)
- Arrow showing progression
- 标题说明转型内容
- 并排对比框
- 视觉指示器(表情符号/图标)
- 展示进展的箭头
4. Process Flow
4. 流程步骤幻灯片
- Sequential numbered cards
- Arrows between steps
- Color progression (gradient)
- End state highlighted
- 带编号的顺序卡片
- 步骤间的箭头
- 渐变色进度
- 突出最终状态
5. Technical Architecture Slide (with Images)
5. 技术架构幻灯片(含图片)
- Header with architecture name
- Official architecture diagram (downloaded from docs)
- Caption with source attribution
- Key points or limitations highlighted in cards
Example: VSCode Extension Limitations Slide
javascript
const pptxgen = require('pptxgenjs');
const { execSync } = require('child_process');
const path = require('path');
async function createTechnicalSlide() {
const pptx = new pptxgen();
pptx.layout = 'LAYOUT_16x9';
// Download VSCode architecture image
const imageUrl = 'https://code.visualstudio.com/assets/api/ux-guidelines/examples/architecture-containers.png';
const imagePath = 'workspace/vscode-architecture.png';
try {
execSync(`curl -o ${imagePath} "${imageUrl}"`, { stdio: 'inherit' });
} catch (error) {
console.log('Image download failed, continuing without image');
}
const slide = pptx.addSlide();
slide.background = { color: 'FFFFFF' };
// Header
slide.addShape(pptx.shapes.RECTANGLE, {
x: 0, y: 0, w: 10, h: 0.8,
fill: { color: 'fc5a1f' }
});
slide.addText('VSCode 插件架构限制', {
x: 0.5, y: 0.18, w: 9, h: 0.45,
fontSize: 26, bold: true, color: 'ffffff',
fontFace: 'Arial'
});
// Left: Architecture image
slide.addImage({
path: imagePath,
x: 0.5, y: 1.2, w: 4.8, h: 2.7
});
slide.addText('VSCode 只对插件开放固定的"插槽"(Containers)', {
x: 0.5, y: 4.0, w: 4.8, h: 0.3,
fontSize: 10, color: '707070', italic: true,
align: 'center'
});
// Right: Limitation cards
slide.addText('API 限制', {
x: 5.5, y: 1.2, w: 4.2, h: 0.4,
fontSize: 18, bold: true, color: 'fc5a1f'
});
// Add limitation cards...
await pptx.writeFile({ fileName: 'technical-slide.pptx' });
}
createTechnicalSlide().catch(console.error);- 标题栏包含架构名称
- 官方架构图(从文档下载)
- 带来源标注的说明
- 卡片突出关键点或限制
示例:VSCode插件架构限制幻灯片
javascript
const pptxgen = require('pptxgenjs');
const { execSync } = require('child_process');
const path = require('path');
async function createTechnicalSlide() {
const pptx = new pptxgen();
pptx.layout = 'LAYOUT_16x9';
// Download VSCode architecture image
const imageUrl = 'https://code.visualstudio.com/assets/api/ux-guidelines/examples/architecture-containers.png';
const imagePath = 'workspace/vscode-architecture.png';
try {
execSync(`curl -o ${imagePath} "${imageUrl}"`, { stdio: 'inherit' });
} catch (error) {
console.log('Image download failed, continuing without image');
}
const slide = pptx.addSlide();
slide.background = { color: 'FFFFFF' };
// Header
slide.addShape(pptx.shapes.RECTANGLE, {
x: 0, y: 0, w: 10, h: 0.8,
fill: { color: 'fc5a1f' }
});
slide.addText('VSCode 插件架构限制', {
x: 0.5, y: 0.18, w: 9, h: 0.45,
fontSize: 26, bold: true, color: 'ffffff',
fontFace: 'Arial'
});
// Left: Architecture image
slide.addImage({
path: imagePath,
x: 0.5, y: 1.2, w: 4.8, h: 2.7
});
slide.addText('VSCode 只对插件开放固定的"插槽"(Containers)', {
x: 0.5, y: 4.0, w: 4.8, h: 0.3,
fontSize: 10, color: '707070', italic: true,
align: 'center'
});
// Right: Limitation cards
slide.addText('API 限制', {
x: 5.5, y: 1.2, w: 4.2, h: 0.4,
fontSize: 18, bold: true, color: 'fc5a1f'
});
// Add limitation cards...
await pptx.writeFile({ fileName: 'technical-slide.pptx' });
}
createTechnicalSlide().catch(console.error);Execution Checklist
执行检查清单
- Analyze content to identify structure
- Choose appropriate design pattern
- Select color palette matching theme
- Search for relevant images (if needed for technical/product content)
- Download images using curl or web tools
- Create PptxGenJS script (include image paths)
- Run script to generate .pptx
- Generate thumbnail preview
- Validate visual quality
- Deliver file and preview to user
- 分析内容确定结构
- 选择合适的设计模式
- 选择匹配主题的配色方案
- 搜索相关图片(技术/产品类内容需要时)
- 使用curl或网页工具下载图片
- 编写PptxGenJS脚本(包含图片路径)
- 运行脚本生成.pptx
- 生成缩略图预览
- 验证视觉质量
- 向用户交付文件和预览
File Output
文件输出
Save files in a dedicated workspace:
bash
mkdir -p workspace
cd workspace
node generate-slide.jsGenerate preview:
bash
python3 /path/to/pptx/scripts/thumbnail.py output.pptx preview --cols 1将文件保存到专用工作区:
bash
mkdir -p workspace
cd workspace
node generate-slide.js生成预览:
bash
python3 /path/to/pptx/scripts/thumbnail.py output.pptx preview --cols 1Modifying Existing PPT Files
修改现有PPT文件
Why PptxGenJS Can't Edit Existing Files?
为什么PptxGenJS无法编辑现有文件?
Technical Reasons:
- Design Focus: PptxGenJS is a "generation" library focused on creating PPTs from scratch
- Complex File Structure: .pptx files are ZIP archives containing multiple XML files (Office Open XML format)
- Relationship Handling: Editing requires parsing complex relationships between slides, shapes, media, etc.
技术原因:
- 设计定位:PptxGenJS是专注于从零创建PPT的「生成型」库
- 复杂文件结构:.pptx文件是包含多个XML文件的ZIP压缩包(Office Open XML格式)
- 关系处理:编辑需要解析幻灯片、形状、媒体等元素之间的复杂关联
Solution: Use pptx-automizer
for Editing Existing Files
pptx-automizer解决方案:使用pptx-automizer
编辑现有文件
pptx-automizerpptx-automizer is a powerful Node.js library specifically designed for editing and merging existing .pptx files.
pptx-automizer是一款功能强大的Node.js库,专门用于编辑和合并现有.pptx文件。
Installation
安装
bash
npm install pptx-automizerbash
npm install pptx-automizeror
or
yarn add pptx-automizer
undefinedyarn add pptx-automizer
undefinedCore Capabilities
核心功能
| Feature | Description |
|---|---|
| Load Templates | Import existing .pptx files as templates |
| Merge Slides | Selectively add slides from multiple templates |
| Modify Elements | Locate and modify shapes by name or creationId |
| Modify Text | Replace text, use tag-based replacement |
| Modify Images | Replace image sources, resize |
| Modify Tables | Update table data and styles |
| Modify Charts | Update chart data (including extended chart types) |
| Import Slide Masters | Preserve original styles and layouts |
| PptxGenJS Integration | Use PptxGenJS to create elements on templates |
| Feature | Description |
|---|---|
| Load Templates | 导入现有.pptx文件作为模板 |
| Merge Slides | 从多个模板中选择性添加幻灯片 |
| Modify Elements | 通过名称或creationId定位并修改形状 |
| Modify Text | 替换文本,支持基于标签的替换 |
| Modify Images | 替换图片源,调整大小 |
| Modify Tables | 更新表格数据和样式 |
| Modify Charts | 更新图表数据(包括扩展图表类型) |
| Import Slide Masters | 保留原始样式和布局 |
| PptxGenJS Integration | 使用PptxGenJS在模板上创建元素 |
Basic Example: Load and Modify Existing PPT
基础示例:加载并修改现有PPT
javascript
import Automizer from 'pptx-automizer';
const automizer = new Automizer({
templateDir: 'path/to/templates',
outputDir: 'path/to/output',
// Keep existing slides (don't truncate)
removeExistingSlides: false,
});
let pres = automizer
// Load root template (output will be based on this)
.loadRoot('MyPresentation.pptx')
// Load same file again to modify its slides
.load('MyPresentation.pptx', 'myPres');
// Add slide 2 from template and modify it
pres.addSlide('myPres', 2, (slide) => {
// Modify element by shape name
slide.modifyElement('Title', [
modify.setText('Updated Title Text'),
]);
slide.modifyElement('ContentBox', [
modify.replaceText([{
replace: '{{placeholder}}',
by: { text: 'Dynamic Content' }
}])
]);
});
// Write output
pres.write('UpdatedPresentation.pptx').then(summary => {
console.log(summary);
});javascript
import Automizer from 'pptx-automizer';
const automizer = new Automizer({
templateDir: 'path/to/templates',
outputDir: 'path/to/output',
// Keep existing slides (don't truncate)
removeExistingSlides: false,
});
let pres = automizer
// Load root template (output will be based on this)
.loadRoot('MyPresentation.pptx')
// Load same file again to modify its slides
.load('MyPresentation.pptx', 'myPres');
// Add slide 2 from template and modify it
pres.addSlide('myPres', 2, (slide) => {
// Modify element by shape name
slide.modifyElement('Title', [
modify.setText('Updated Title Text'),
]);
slide.modifyElement('ContentBox', [
modify.replaceText([{
replace: '{{placeholder}}',
by: { text: 'Dynamic Content' }
}])
]);
});
// Write output
pres.write('UpdatedPresentation.pptx').then(summary => {
console.log(summary);
});Modify Single Slide in Existing PPT
修改现有PPT中的单页幻灯片
javascript
import Automizer, { modify, ModifyTextHelper } from 'pptx-automizer';
async function modifySingleSlide(inputFile, slideNumber, modifications) {
const automizer = new Automizer({
templateDir: './',
outputDir: './',
removeExistingSlides: true, // Start fresh
});
// Load the file twice - as root and as template
let pres = automizer
.loadRoot(inputFile)
.load(inputFile, 'source');
// Get all slide numbers
const slideNumbers = await pres
.getTemplate('source')
.getAllSlideNumbers();
// Re-add all slides, modifying only the target slide
for (const num of slideNumbers) {
if (num === slideNumber) {
// Apply modifications to target slide
pres.addSlide('source', num, modifications);
} else {
// Keep other slides unchanged
pres.addSlide('source', num);
}
}
// Write to new file (or same file)
await pres.write(inputFile.replace('.pptx', '-modified.pptx'));
}
// Usage:
await modifySingleSlide('plugin-to-ide.pptx', 1, (slide) => {
slide.modifyElement('Title', [
ModifyTextHelper.setText('New Title'),
]);
});javascript
import Automizer, { modify, ModifyTextHelper } from 'pptx-automizer';
async function modifySingleSlide(inputFile, slideNumber, modifications) {
const automizer = new Automizer({
templateDir: './',
outputDir: './',
removeExistingSlides: true, // Start fresh
});
// Load the file twice - as root and as template
let pres = automizer
.loadRoot(inputFile)
.load(inputFile, 'source');
// Get all slide numbers
const slideNumbers = await pres
.getTemplate('source')
.getAllSlideNumbers();
// Re-add all slides, modifying only the target slide
for (const num of slideNumbers) {
if (num === slideNumber) {
// Apply modifications to target slide
pres.addSlide('source', num, modifications);
} else {
// Keep other slides unchanged
pres.addSlide('source', num);
}
}
// Write to new file (or same file)
await pres.write(inputFile.replace('.pptx', '-modified.pptx'));
}
// Usage:
await modifySingleSlide('plugin-to-ide.pptx', 1, (slide) => {
slide.modifyElement('Title', [
ModifyTextHelper.setText('New Title'),
]);
});Modify Chart Data in Existing PPT
修改现有PPT中的图表数据
javascript
import Automizer, { modify } from 'pptx-automizer';
pres.addSlide('charts', 2, (slide) => {
slide.modifyElement('ColumnChart', [
modify.setChartData({
series: [
{ label: 'Q1 Sales' },
{ label: 'Q2 Sales' },
],
categories: [
{ label: 'Product A', values: [150, 180] },
{ label: 'Product B', values: [200, 220] },
{ label: 'Product C', values: [130, 160] },
],
}),
]);
});javascript
import Automizer, { modify } from 'pptx-automizer';
pres.addSlide('charts', 2, (slide) => {
slide.modifyElement('ColumnChart', [
modify.setChartData({
series: [
{ label: 'Q1 Sales' },
{ label: 'Q2 Sales' },
],
categories: [
{ label: 'Product A', values: [150, 180] },
{ label: 'Product B', values: [200, 220] },
{ label: 'Product C', values: [130, 160] },
],
}),
]);
});Replace Images in Existing PPT
替换现有PPT中的图片
javascript
import Automizer, { ModifyImageHelper, ModifyShapeHelper, CmToDxa } from 'pptx-automizer';
const automizer = new Automizer({
templateDir: 'templates',
outputDir: 'output',
mediaDir: 'images', // Directory for external images
});
let pres = automizer
.loadRoot('Template.pptx')
.loadMedia(['new-image.png']) // Load external image
.load('Template.pptx', 'template');
pres.addSlide('template', 1, (slide) => {
slide.modifyElement('ImagePlaceholder', [
// Replace image source
ModifyImageHelper.setRelationTarget('new-image.png'),
// Optionally adjust size
ModifyShapeHelper.setPosition({
w: CmToDxa(8),
h: CmToDxa(6),
}),
]);
});
pres.write('UpdatedWithNewImage.pptx');javascript
import Automizer, { ModifyImageHelper, ModifyShapeHelper, CmToDxa } from 'pptx-automizer';
const automizer = new Automizer({
templateDir: 'templates',
outputDir: 'output',
mediaDir: 'images', // Directory for external images
});
let pres = automizer
.loadRoot('Template.pptx')
.loadMedia(['new-image.png']) // Load external image
.load('Template.pptx', 'template');
pres.addSlide('template', 1, (slide) => {
slide.modifyElement('ImagePlaceholder', [
// Replace image source
ModifyImageHelper.setRelationTarget('new-image.png'),
// Optionally adjust size
ModifyShapeHelper.setPosition({
w: CmToDxa(8),
h: CmToDxa(6),
}),
]);
});
pres.write('UpdatedWithNewImage.pptx');Use Tag-Based Text Replacement
使用基于标签的文本替换
PowerPoint shapes can contain placeholder tags like that get replaced:
{{title}}javascript
pres.addSlide('template', 1, (slide) => {
slide.modifyElement('TextWithTags', [
modify.replaceText([
{ replace: 'title', by: { text: 'My Dynamic Title' } },
{ replace: 'date', by: { text: '2026-02-28' } },
{ replace: 'author', by: { text: 'Your Name' } },
]),
]);
});PowerPoint形状可包含这类占位符标签,用于替换内容:
{{title}}javascript
pres.addSlide('template', 1, (slide) => {
slide.modifyElement('TextWithTags', [
modify.replaceText([
{ replace: 'title', by: { text: 'My Dynamic Title' } },
{ replace: 'date', by: { text: '2026-02-28' } },
{ replace: 'author', by: { text: 'Your Name' } },
]),
]);
});Comparison: PptxGenJS vs pptx-automizer
对比:PptxGenJS vs pptx-automizer
| Feature | PptxGenJS | pptx-automizer |
|---|---|---|
| Create from scratch | ✅ Excellent | ⚠️ Limited (wraps PptxGenJS) |
| Edit existing files | ❌ No | ✅ Yes |
| Merge templates | ❌ No | ✅ Yes |
| Preserve styles | ❌ N/A | ✅ Yes |
| Modify charts | ❌ No | ✅ Yes |
| Tag replacement | ❌ No | ✅ Yes |
| Learning curve | Low | Medium |
| Feature | PptxGenJS | pptx-automizer |
|---|---|---|
| Create from scratch | ✅ Excellent | ⚠️ Limited (wraps PptxGenJS) |
| Edit existing files | ❌ No | ✅ Yes |
| Merge templates | ❌ No | ✅ Yes |
| Preserve styles | ❌ N/A | ✅ Yes |
| Modify charts | ❌ No | ✅ Yes |
| Tag replacement | ❌ No | ✅ Yes |
| Learning curve | Low | Medium |
Recommended Workflow
推荐工作流
For creating new PPTs: Use PptxGenJS
For editing existing PPTs: Use pptx-automizer
For hybrid workflows: Use pptx-automizer with PptxGenJS integration
javascript
// pptx-automizer can wrap PptxGenJS for creating new elements
pres.addSlide('template', 1, (slide) => {
// Use pptxgenjs to add new shapes from scratch
slide.generate((pptxGenJSSlide, pptxGenJs) => {
pptxGenJSSlide.addText('New Text Box', {
x: 1, y: 1, w: 3, h: 0.5,
fontSize: 14, color: '333333'
});
pptxGenJSSlide.addChart(pptxGenJs.ChartType.bar, chartData, {
x: 4, y: 1, w: 5, h: 3
});
});
});创建新PPT:使用PptxGenJS
编辑现有PPT:使用pptx-automizer
混合工作流:使用集成PptxGenJS的pptx-automizer
javascript
// pptx-automizer can wrap PptxGenJS for creating new elements
pres.addSlide('template', 1, (slide) => {
// Use pptxgenjs to add new shapes from scratch
slide.generate((pptxGenJSSlide, pptxGenJs) => {
pptxGenJSSlide.addText('New Text Box', {
x: 1, y: 1, w: 3, h: 0.5,
fontSize: 14, color: '333333'
});
pptxGenJSSlide.addChart(pptxGenJs.ChartType.bar, chartData, {
x: 4, y: 1, w: 5, h: 3
});
});
});Shape Selection Methods
形状选择方法
By Shape Name (Simple)
通过形状名称(简单)
javascript
slide.modifyElement('MyShapeName', [ /* modifiers */ ]);javascript
slide.modifyElement('MyShapeName', [ /* modifiers */ ]);By creationId (Robust)
通过creationId(可靠)
javascript
// More stable - survives slide rearrangement
slide.modifyElement('{E43D12C3-AD5A-4317-BC00-FDED287C0BE8}', [ /* modifiers */ ]);javascript
// More stable - survives slide rearrangement
slide.modifyElement('{E43D12C3-AD5A-4317-BC00-FDED287C0BE8}', [ /* modifiers */ ]);With Fallback
带回退机制
javascript
slide.modifyElement({
creationId: '{E43D12C3-AD5A-4317-BC00-FDED287C0BE8}',
name: 'MyShapeName', // Fallback if creationId not found
}, [ /* modifiers */ ]);javascript
slide.modifyElement({
creationId: '{E43D12C3-AD5A-4317-BC00-FDED287C0BE8}',
name: 'MyShapeName', // Fallback if creationId not found
}, [ /* modifiers */ ]);Best Practices
最佳实践
- Template Management: Keep a library of well-designed .pptx templates
- Shape Naming: Give shapes meaningful names in PowerPoint (ALT+F10 to open Selection Pane)
- Tag Convention: Use consistent tag format like
{{tagName}} - Version Control: Track changes to templates in git
- Preview After Edit: Always generate thumbnails to verify changes
- Error Handling: Handle missing shapes gracefully
- 模板管理:维护一个设计精良的.pptx模板库
- 形状命名:在PowerPoint中为形状赋予有意义的名称(按ALT+F10打开选择窗格)
- 标签约定:使用一致的标签格式如
{{tagName}} - 版本控制:在git中跟踪模板的变更
- 编辑后预览:始终生成缩略图验证变更
- 错误处理:优雅处理缺失的形状
Notes
注意事项
- No # prefix in colors: Use not
"ff6b6b"(causes corruption)"#ff6b6b" - Web-safe fonts only: Arial, Helvetica, Times New Roman, Georgia, Courier New, Verdana
- Test emoji support: Some emoji may not render on all platforms
- 16:9 aspect ratio: Standard for most presentations (10 x 5.625 inches)
- pptx-automizer: Use for editing existing .pptx files
- PptxGenJS: Use for creating new presentations from scratch
- 颜色不要加#前缀:使用而非
"ff6b6b"(会导致文件损坏)"#ff6b6b" - 仅使用Web安全字体:Arial、Helvetica、Times New Roman、Georgia、Courier New、Verdana
- 测试表情符号支持:部分表情符号可能无法在所有平台渲染
- 16:9宽高比:大多数演示的标准格式(10 x 5.625英寸)
- pptx-automizer:用于编辑现有.pptx文件
- PptxGenJS:用于从零创建演示文稿