Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Create, edit, and inspect PowerPoint presentations with professional design and automated visual QA
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
pptxgenjs.md
1# PptxGenJS Tutorial23## Setup & Basic Structure45```javascript6const pptxgen = require("pptxgenjs");78let pres = new pptxgen();9pres.layout = 'LAYOUT_16x9'; // or 'LAYOUT_16x10', 'LAYOUT_4x3', 'LAYOUT_WIDE'10pres.author = 'Your Name';11pres.title = 'Presentation Title';1213let slide = pres.addSlide();14slide.addText("Hello World!", { x: 0.5, y: 0.5, fontSize: 36, color: "363636" });1516pres.writeFile({ fileName: "Presentation.pptx" });17```1819## Layout Dimensions2021Slide dimensions (coordinates in inches):22- `LAYOUT_16x9`: 10" × 5.625" (default)23- `LAYOUT_16x10`: 10" × 6.25"24- `LAYOUT_4x3`: 10" × 7.5"25- `LAYOUT_WIDE`: 13.3" × 7.5"2627---2829## Text & Formatting3031```javascript32// Basic text33slide.addText("Simple Text", {34x: 1, y: 1, w: 8, h: 2, fontSize: 24, fontFace: "Arial",35color: "363636", bold: true, align: "center", valign: "middle"36});3738// Character spacing (use charSpacing, not letterSpacing which is silently ignored)39slide.addText("SPACED TEXT", { x: 1, y: 1, w: 8, h: 1, charSpacing: 6 });4041// Rich text arrays42slide.addText([43{ text: "Bold ", options: { bold: true } },44{ text: "Italic ", options: { italic: true } }45], { x: 1, y: 3, w: 8, h: 1 });4647// Multi-line text (requires breakLine: true)48slide.addText([49{ text: "Line 1", options: { breakLine: true } },50{ text: "Line 2", options: { breakLine: true } },51{ text: "Line 3" } // Last item doesn't need breakLine52], { x: 0.5, y: 0.5, w: 8, h: 2 });5354// Text box margin (internal padding)55slide.addText("Title", {56x: 0.5, y: 0.3, w: 9, h: 0.6,57margin: 0 // Use 0 when aligning text with other elements like shapes or icons58});59```6061**Tip:** Text boxes have internal margin by default. Set `margin: 0` when you need text to align precisely with shapes, lines, or icons at the same x-position.6263---6465## Lists & Bullets6667```javascript68// ✅ CORRECT: Multiple bullets69slide.addText([70{ text: "First item", options: { bullet: true, breakLine: true } },71{ text: "Second item", options: { bullet: true, breakLine: true } },72{ text: "Third item", options: { bullet: true } }73], { x: 0.5, y: 0.5, w: 8, h: 3 });7475// ❌ WRONG: Never use unicode bullets76slide.addText("• First item", { ... }); // Creates double bullets7778// Sub-items and numbered lists79{ text: "Sub-item", options: { bullet: true, indentLevel: 1 } }80{ text: "First", options: { bullet: { type: "number" }, breakLine: true } }81```8283---8485## Shapes8687```javascript88slide.addShape(pres.shapes.RECTANGLE, {89x: 0.5, y: 0.8, w: 1.5, h: 3.0,90fill: { color: "FF0000" }, line: { color: "000000", width: 2 }91});9293slide.addShape(pres.shapes.OVAL, { x: 4, y: 1, w: 2, h: 2, fill: { color: "0000FF" } });9495slide.addShape(pres.shapes.LINE, {96x: 1, y: 3, w: 5, h: 0, line: { color: "FF0000", width: 3, dashType: "dash" }97});9899// With transparency100slide.addShape(pres.shapes.RECTANGLE, {101x: 1, y: 1, w: 3, h: 2,102fill: { color: "0088CC", transparency: 50 }103});104105// Rounded rectangle (rectRadius only works with ROUNDED_RECTANGLE, not RECTANGLE)106// ⚠️ Don't pair with rectangular accent overlays — they won't cover rounded corners. Use RECTANGLE instead.107slide.addShape(pres.shapes.ROUNDED_RECTANGLE, {108x: 1, y: 1, w: 3, h: 2,109fill: { color: "FFFFFF" }, rectRadius: 0.1110});111112// With shadow113slide.addShape(pres.shapes.RECTANGLE, {114x: 1, y: 1, w: 3, h: 2,115fill: { color: "FFFFFF" },116shadow: { type: "outer", color: "000000", blur: 6, offset: 2, angle: 135, opacity: 0.15 }117});118```119120Shadow options:121122| Property | Type | Range | Notes |123|----------|------|-------|-------|124| `type` | string | `"outer"`, `"inner"` | |125| `color` | string | 6-char hex (e.g. `"000000"`) | No `#` prefix, no 8-char hex — see Common Pitfalls |126| `blur` | number | 0-100 pt | |127| `offset` | number | 0-200 pt | **Must be non-negative** — negative values corrupt the file |128| `angle` | number | 0-359 degrees | Direction the shadow falls (135 = bottom-right, 270 = upward) |129| `opacity` | number | 0.0-1.0 | Use this for transparency, never encode in color string |130131To cast a shadow upward (e.g. on a footer bar), use `angle: 270` with a positive offset — do **not** use a negative offset.132133**Note**: Gradient fills are not natively supported. Use a gradient image as a background instead.134135---136137## Images138139### Image Sources140141```javascript142// From file path143slide.addImage({ path: "images/chart.png", x: 1, y: 1, w: 5, h: 3 });144145// From URL146slide.addImage({ path: "https://example.com/image.jpg", x: 1, y: 1, w: 5, h: 3 });147148// From base64 (faster, no file I/O)149slide.addImage({ data: "image/png;base64,iVBORw0KGgo...", x: 1, y: 1, w: 5, h: 3 });150```151152### Image Options153154```javascript155slide.addImage({156path: "image.png",157x: 1, y: 1, w: 5, h: 3,158rotate: 45, // 0-359 degrees159rounding: true, // Circular crop160transparency: 50, // 0-100161flipH: true, // Horizontal flip162flipV: false, // Vertical flip163altText: "Description", // Accessibility164hyperlink: { url: "https://example.com" }165});166```167168### Image Sizing Modes169170```javascript171// Contain - fit inside, preserve ratio172{ sizing: { type: 'contain', w: 4, h: 3 } }173174// Cover - fill area, preserve ratio (may crop)175{ sizing: { type: 'cover', w: 4, h: 3 } }176177// Crop - cut specific portion178{ sizing: { type: 'crop', x: 0.5, y: 0.5, w: 2, h: 2 } }179```180181### Calculate Dimensions (preserve aspect ratio)182183```javascript184const origWidth = 1978, origHeight = 923, maxHeight = 3.0;185const calcWidth = maxHeight * (origWidth / origHeight);186const centerX = (10 - calcWidth) / 2;187188slide.addImage({ path: "image.png", x: centerX, y: 1.2, w: calcWidth, h: maxHeight });189```190191### Supported Formats192193- **Standard**: PNG, JPG, GIF (animated GIFs work in Microsoft 365)194- **SVG**: Works in modern PowerPoint/Microsoft 365195196---197198## Icons199200Use react-icons to generate SVG icons, then rasterize to PNG for universal compatibility.201202### Setup203204```javascript205const React = require("react");206const ReactDOMServer = require("react-dom/server");207const sharp = require("sharp");208const { FaCheckCircle, FaChartLine } = require("react-icons/fa");209210function renderIconSvg(IconComponent, color = "#000000", size = 256) {211return ReactDOMServer.renderToStaticMarkup(212React.createElement(IconComponent, { color, size: String(size) })213);214}215216async function iconToBase64Png(IconComponent, color, size = 256) {217const svg = renderIconSvg(IconComponent, color, size);218const pngBuffer = await sharp(Buffer.from(svg)).png().toBuffer();219return "image/png;base64," + pngBuffer.toString("base64");220}221```222223### Add Icon to Slide224225```javascript226const iconData = await iconToBase64Png(FaCheckCircle, "#4472C4", 256);227228slide.addImage({229data: iconData,230x: 1, y: 1, w: 0.5, h: 0.5 // Size in inches231});232```233234**Note**: Use size 256 or higher for crisp icons. The size parameter controls the rasterization resolution, not the display size on the slide (which is set by `w` and `h` in inches).235236### Icon Libraries237238Install: `npm install -g react-icons react react-dom sharp`239240Popular icon sets in react-icons:241- `react-icons/fa` - Font Awesome242- `react-icons/md` - Material Design243- `react-icons/hi` - Heroicons244- `react-icons/bi` - Bootstrap Icons245246---247248## Slide Backgrounds249250```javascript251// Solid color252slide.background = { color: "F1F1F1" };253254// Color with transparency255slide.background = { color: "FF3399", transparency: 50 };256257// Image from URL258slide.background = { path: "https://example.com/bg.jpg" };259260// Image from base64261slide.background = { data: "image/png;base64,iVBORw0KGgo..." };262```263264---265266## Tables267268```javascript269slide.addTable([270["Header 1", "Header 2"],271["Cell 1", "Cell 2"]272], {273x: 1, y: 1, w: 8, h: 2,274border: { pt: 1, color: "999999" }, fill: { color: "F1F1F1" }275});276277// Advanced with merged cells278let tableData = [279[{ text: "Header", options: { fill: { color: "6699CC" }, color: "FFFFFF", bold: true } }, "Cell"],280[{ text: "Merged", options: { colspan: 2 } }]281];282slide.addTable(tableData, { x: 1, y: 3.5, w: 8, colW: [4, 4] });283```284285---286287## Charts288289```javascript290// Bar chart291slide.addChart(pres.charts.BAR, [{292name: "Sales", labels: ["Q1", "Q2", "Q3", "Q4"], values: [4500, 5500, 6200, 7100]293}], {294x: 0.5, y: 0.6, w: 6, h: 3, barDir: 'col',295showTitle: true, title: 'Quarterly Sales'296});297298// Line chart299slide.addChart(pres.charts.LINE, [{300name: "Temp", labels: ["Jan", "Feb", "Mar"], values: [32, 35, 42]301}], { x: 0.5, y: 4, w: 6, h: 3, lineSize: 3, lineSmooth: true });302303// Pie chart304slide.addChart(pres.charts.PIE, [{305name: "Share", labels: ["A", "B", "Other"], values: [35, 45, 20]306}], { x: 7, y: 1, w: 5, h: 4, showPercent: true });307```308309### Better-Looking Charts310311Default charts look dated. Apply these options for a modern, clean appearance:312313```javascript314slide.addChart(pres.charts.BAR, chartData, {315x: 0.5, y: 1, w: 9, h: 4, barDir: "col",316317// Custom colors (match your presentation palette)318chartColors: ["0D9488", "14B8A6", "5EEAD4"],319320// Clean background321chartArea: { fill: { color: "FFFFFF" }, roundedCorners: true },322323// Muted axis labels324catAxisLabelColor: "64748B",325valAxisLabelColor: "64748B",326327// Subtle grid (value axis only)328valGridLine: { color: "E2E8F0", size: 0.5 },329catGridLine: { style: "none" },330331// Data labels on bars332showValue: true,333dataLabelPosition: "outEnd",334dataLabelColor: "1E293B",335336// Hide legend for single series337showLegend: false,338});339```340341**Key styling options:**342- `chartColors: [...]` - hex colors for series/segments343- `chartArea: { fill, border, roundedCorners }` - chart background344- `catGridLine/valGridLine: { color, style, size }` - grid lines (`style: "none"` to hide)345- `lineSmooth: true` - curved lines (line charts)346- `legendPos: "r"` - legend position: "b", "t", "l", "r", "tr"347348---349350## Slide Masters351352```javascript353pres.defineSlideMaster({354title: 'TITLE_SLIDE', background: { color: '283A5E' },355objects: [{356placeholder: { options: { name: 'title', type: 'title', x: 1, y: 2, w: 8, h: 2 } }357}]358});359360let titleSlide = pres.addSlide({ masterName: "TITLE_SLIDE" });361titleSlide.addText("My Title", { placeholder: "title" });362```363364---365366## Common Pitfalls367368⚠️ These issues cause file corruption, visual bugs, or broken output. Avoid them.3693701. **NEVER use "#" with hex colors** - causes file corruption371```javascript372color: "FF0000" // ✅ CORRECT373color: "#FF0000" // ❌ WRONG374```3753762. **NEVER encode opacity in hex color strings** - 8-char colors (e.g., `"00000020"`) corrupt the file. Use the `opacity` property instead.377```javascript378shadow: { type: "outer", blur: 6, offset: 2, color: "00000020" } // ❌ CORRUPTS FILE379shadow: { type: "outer", blur: 6, offset: 2, color: "000000", opacity: 0.12 } // ✅ CORRECT380```3813823. **Use `bullet: true`** - NEVER unicode symbols like "•" (creates double bullets)3833844. **Use `breakLine: true`** between array items or text runs together3853865. **Avoid `lineSpacing` with bullets** - causes excessive gaps; use `paraSpaceAfter` instead3873886. **Each presentation needs fresh instance** - don't reuse `pptxgen()` objects3893907. **NEVER reuse option objects across calls** - PptxGenJS mutates objects in-place (e.g. converting shadow values to EMU). Sharing one object between multiple calls corrupts the second shape.391```javascript392const shadow = { type: "outer", blur: 6, offset: 2, color: "000000", opacity: 0.15 };393slide.addShape(pres.shapes.RECTANGLE, { shadow, ... }); // ❌ second call gets already-converted values394slide.addShape(pres.shapes.RECTANGLE, { shadow, ... });395396const makeShadow = () => ({ type: "outer", blur: 6, offset: 2, color: "000000", opacity: 0.15 });397slide.addShape(pres.shapes.RECTANGLE, { shadow: makeShadow(), ... }); // ✅ fresh object each time398slide.addShape(pres.shapes.RECTANGLE, { shadow: makeShadow(), ... });399```4004018. **Don't use `ROUNDED_RECTANGLE` with accent borders** - rectangular overlay bars won't cover rounded corners. Use `RECTANGLE` instead.402```javascript403// ❌ WRONG: Accent bar doesn't cover rounded corners404slide.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: 1, y: 1, w: 3, h: 1.5, fill: { color: "FFFFFF" } });405slide.addShape(pres.shapes.RECTANGLE, { x: 1, y: 1, w: 0.08, h: 1.5, fill: { color: "0891B2" } });406407// ✅ CORRECT: Use RECTANGLE for clean alignment408slide.addShape(pres.shapes.RECTANGLE, { x: 1, y: 1, w: 3, h: 1.5, fill: { color: "FFFFFF" } });409slide.addShape(pres.shapes.RECTANGLE, { x: 1, y: 1, w: 0.08, h: 1.5, fill: { color: "0891B2" } });410```411412---413414## Quick Reference415416- **Shapes**: RECTANGLE, OVAL, LINE, ROUNDED_RECTANGLE417- **Charts**: BAR, LINE, PIE, DOUGHNUT, SCATTER, BUBBLE, RADAR418- **Layouts**: LAYOUT_16x9 (10"×5.625"), LAYOUT_16x10, LAYOUT_4x3, LAYOUT_WIDE419- **Alignment**: "left", "center", "right"420- **Chart data labels**: "outEnd", "inEnd", "center"421