single-slide-ppt

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Single-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:
  1. Official documentation: Search for "[Product Name] architecture documentation" or "[Product Name] official API documentation"
  2. GitHub repositories: Look for diagrams in README.md or docs/ folders
  3. Technical blogs: Find explanation diagrams from reputable sources
  4. 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'
);
图片查找策略
  1. 官方文档:搜索「[产品名称] 架构文档」或「[产品名称] 官方API文档」
  2. GitHub仓库:查看README.md或docs/文件夹中的图表
  3. 技术博客:从权威来源查找解释性图表
  4. 使用搜索工具:搜索相关内容并提取图片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:
    rgba(R,G,B,0.1)
    becomes
    RRGGBB
    + lighter fill
  • 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

视觉层级

  1. Title/header (largest, highest contrast)
  2. Section headers (medium, color-coded)
  3. Content cards (grouped, bordered)
  4. Supporting text (smallest, lower contrast)
  1. 标题/标题栏(字号最大,对比度最高)
  2. 板块标题(中等字号,颜色编码)
  3. 内容卡片(分组,带边框)
  4. 辅助文本(字号最小,对比度较低)

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.js
Generate 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 1

Modifying Existing PPT Files

修改现有PPT文件

Why PptxGenJS Can't Edit Existing Files?

为什么PptxGenJS无法编辑现有文件?

Technical Reasons:
  1. Design Focus: PptxGenJS is a "generation" library focused on creating PPTs from scratch
  2. Complex File Structure: .pptx files are ZIP archives containing multiple XML files (Office Open XML format)
  3. Relationship Handling: Editing requires parsing complex relationships between slides, shapes, media, etc.
技术原因
  1. 设计定位:PptxGenJS是专注于从零创建PPT的「生成型」库
  2. 复杂文件结构:.pptx文件是包含多个XML文件的ZIP压缩包(Office Open XML格式)
  3. 关系处理:编辑需要解析幻灯片、形状、媒体等元素之间的复杂关联

Solution: Use
pptx-automizer
for Editing Existing Files

解决方案:使用
pptx-automizer
编辑现有文件

pptx-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-automizer
bash
npm install pptx-automizer

or

or

yarn add pptx-automizer
undefined
yarn add pptx-automizer
undefined

Core Capabilities

核心功能

FeatureDescription
Load TemplatesImport existing .pptx files as templates
Merge SlidesSelectively add slides from multiple templates
Modify ElementsLocate and modify shapes by name or creationId
Modify TextReplace text, use tag-based replacement
Modify ImagesReplace image sources, resize
Modify TablesUpdate table data and styles
Modify ChartsUpdate chart data (including extended chart types)
Import Slide MastersPreserve original styles and layouts
PptxGenJS IntegrationUse PptxGenJS to create elements on templates
FeatureDescription
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
{{title}}
that get replaced:
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

FeaturePptxGenJSpptx-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 curveLowMedium
FeaturePptxGenJSpptx-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 curveLowMedium

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

最佳实践

  1. Template Management: Keep a library of well-designed .pptx templates
  2. Shape Naming: Give shapes meaningful names in PowerPoint (ALT+F10 to open Selection Pane)
  3. Tag Convention: Use consistent tag format like
    {{tagName}}
  4. Version Control: Track changes to templates in git
  5. Preview After Edit: Always generate thumbnails to verify changes
  6. Error Handling: Handle missing shapes gracefully
  1. 模板管理:维护一个设计精良的.pptx模板库
  2. 形状命名:在PowerPoint中为形状赋予有意义的名称(按ALT+F10打开选择窗格)
  3. 标签约定:使用一致的标签格式如
    {{tagName}}
  4. 版本控制:在git中跟踪模板的变更
  5. 编辑后预览:始终生成缩略图验证变更
  6. 错误处理:优雅处理缺失的形状

Notes

注意事项

  • No # prefix in colors: Use
    "ff6b6b"
    not
    "#ff6b6b"
    (causes corruption)
  • 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:用于从零创建演示文稿