
Pptx
- 188k installs
- 165k repo stars
- Updated July 24, 2026
- anthropics/skills
pptx is a skill for creating and editing PowerPoint presentations with design discipline, color-palette rules, and exhaustive visual QA loops.
About
pptx is a comprehensive skill for reading, editing, and creating PowerPoint presentations. It covers text extraction with markitdown, unpack-edit-pack workflows for templates, and from-scratch creation with pptxgenjs. The skill enforces design discipline: bold content-specific color palettes, high typographic contrast, visual motifs, and exhaustive QA via subagent visual inspection. Developers reach for pptx when any .pptx file is involved as input, output, or reference.
- Text extraction via `python -m markitdown`, visual inspection via thumbnail grids, programmatic creation via pptxgenjs
- Design directives: bold color palette (60-70% dominant, 1-2 supporting, 1 accent), visual motif per slide, no gradients
- QA loop with subagent visual inspection catching overlaps, text overflow, low contrast, and placeholder content
Pptx by the numbers
- 187,696 all-time installs (skills.sh)
- +7,215 installs in the week ending Jul 28, 2026 (Skillselion tracking)
- Ranked #11 of 690 Office & Documents skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Jul 28, 2026 (Skillselion catalog sync)
pptx capabilities & compatibility
- Capabilities
- presentation design · slide creation · content extraction · template editing
- Platforms
- macOS · Windows · Linux
npx skills add https://github.com/anthropics/skills --skill pptxAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 188k |
|---|---|
| repo stars | ★ 165k |
| Security audit | 3 / 3 scanners passed |
| Last updated | July 24, 2026 |
| Repository | anthropics/skills ↗ |
How do you generate PowerPoint files with an AI agent?
Create, edit, analyze, and design PowerPoint presentations with comprehensive QA and design guidance
Who is it for?
Developers creating pitch decks, product documentation, or presentations who need design guidance and visual QA via subagents
Skip if: Static PDF export or presentations where generic white-background bullet-point slides are acceptable
When should I use this skill?
Any .pptx file is involved: creating deck, reading content, editing, or combining slides
What you get
Editable .pptx PowerPoint file with slides derived from supplied content or instructions
- Editable .pptx file
Files
PPTX Skill
Quick Reference
| Task | Guide |
|---|---|
| Read/analyze content | python -m markitdown presentation.pptx |
| Edit or create from template | Read editing.md |
| Create from scratch | Read pptxgenjs.md |
---
Reading Content
# Text extraction
python -m markitdown presentation.pptx
# Visual overview
python scripts/thumbnail.py presentation.pptx
# Raw XML
python scripts/office/unpack.py presentation.pptx unpacked/---
Editing Workflow
Read [editing.md](editing.md) for full details.
1. Analyze template with thumbnail.py 2. Unpack → manipulate slides → edit content → clean → pack
---
Creating from Scratch
Read [pptxgenjs.md](pptxgenjs.md) for full details.
Use when no template or reference presentation is available.
---
Design Ideas
Don't create boring slides. Plain bullets on a white background won't impress anyone. Consider ideas from this list for each slide.
Before Starting
- Pick a bold, content-informed color palette: The palette should feel designed for THIS topic. If swapping your colors into a completely different presentation would still "work," you haven't made specific enough choices.
- Dominance over equality: One color should dominate (60-70% visual weight), with 1-2 supporting tones and one sharp accent. Never give all colors equal weight.
- Dark/light contrast: Dark backgrounds for title + conclusion slides, light for content ("sandwich" structure). Or commit to dark throughout for a premium feel.
- Commit to a visual motif: Pick ONE distinctive element and repeat it — rounded image frames, icons in colored circles, thick single-side borders. Carry it across every slide.
Color Palettes
Choose colors that match your topic — don't default to generic blue. Use these palettes as inspiration:
| Theme | Primary | Secondary | Accent |
|---|---|---|---|
| Midnight Executive | 1E2761 (navy) | CADCFC (ice blue) | FFFFFF (white) |
| Forest & Moss | 2C5F2D (forest) | 97BC62 (moss) | F5F5F5 (cream) |
| Coral Energy | F96167 (coral) | F9E795 (gold) | 2F3C7E (navy) |
| Warm Terracotta | B85042 (terracotta) | E7E8D1 (sand) | A7BEAE (sage) |
| Ocean Gradient | 065A82 (deep blue) | 1C7293 (teal) | 21295C (midnight) |
| Charcoal Minimal | 36454F (charcoal) | F2F2F2 (off-white) | 212121 (black) |
| Teal Trust | 028090 (teal) | 00A896 (seafoam) | 02C39A (mint) |
| Berry & Cream | 6D2E46 (berry) | A26769 (dusty rose) | ECE2D0 (cream) |
| Sage Calm | 84B59F (sage) | 69A297 (eucalyptus) | 50808E (slate) |
| Cherry Bold | 990011 (cherry) | FCF6F5 (off-white) | 2F3C7E (navy) |
For Each Slide
Every slide needs a visual element — image, chart, icon, or shape. Text-only slides are forgettable.
Layout options:
- Two-column (text left, illustration on right)
- Icon + text rows (icon in colored circle, bold header, description below)
- 2x2 or 2x3 grid (image on one side, grid of content blocks on other)
- Half-bleed image (full left or right side) with content overlay
Data display:
- Large stat callouts (big numbers 60-72pt with small labels below)
- Comparison columns (before/after, pros/cons, side-by-side options)
- Timeline or process flow (numbered steps, arrows)
Visual polish:
- Icons in small colored circles next to section headers
- Italic accent text for key stats or taglines
Typography
Choose an interesting font pairing — don't default to Arial. Pick a header font with personality and pair it with a clean body font.
| Header Font | Body Font |
|---|---|
| Georgia | Calibri |
| Arial Black | Arial |
| Calibri | Calibri Light |
| Cambria | Calibri |
| Trebuchet MS | Calibri |
| Impact | Arial |
| Palatino | Garamond |
| Consolas | Calibri |
| Element | Size |
|---|---|
| Slide title | 36-44pt bold |
| Section header | 20-24pt bold |
| Body text | 14-16pt |
| Captions | 10-12pt muted |
Spacing
- 0.5" minimum margins
- 0.3-0.5" between content blocks
- Leave breathing room—don't fill every inch
Avoid (Common Mistakes)
- Don't repeat the same layout — vary columns, cards, and callouts across slides
- Don't center body text — left-align paragraphs and lists; center only titles
- Don't skimp on size contrast — titles need 36pt+ to stand out from 14-16pt body
- Don't default to blue — pick colors that reflect the specific topic
- Don't mix spacing randomly — choose 0.3" or 0.5" gaps and use consistently
- Don't style one slide and leave the rest plain — commit fully or keep it simple throughout
- Don't create text-only slides — add images, icons, charts, or visual elements; avoid plain title + bullets
- Don't forget text box padding — when aligning lines or shapes with text edges, set
margin: 0on the text box or offset the shape to account for padding - Don't use low-contrast elements — icons AND text need strong contrast against the background; avoid light text on light backgrounds or dark text on dark backgrounds
- NEVER use accent lines under titles — these are a hallmark of AI-generated slides; use whitespace or background color instead
---
QA (Required)
Assume there are problems. Your job is to find them.
Your first render is almost never correct. Approach QA as a bug hunt, not a confirmation step. If you found zero issues on first inspection, you weren't looking hard enough.
Content QA
python -m markitdown output.pptxCheck for missing content, typos, wrong order.
When using templates, check for leftover placeholder text:
python -m markitdown output.pptx | grep -iE "xxxx|lorem|ipsum|this.*(page|slide).*layout"If grep returns results, fix them before declaring success.
Visual QA
⚠️ USE SUBAGENTS — even for 2-3 slides. You've been staring at the code and will see what you expect, not what's there. Subagents have fresh eyes.
Convert slides to images (see Converting to Images), then use this prompt:
Visually inspect these slides. Assume there are issues — find them.
Look for:
- Overlapping elements (text through shapes, lines through words, stacked elements)
- Text overflow or cut off at edges/box boundaries
- Decorative lines positioned for single-line text but title wrapped to two lines
- Source citations or footers colliding with content above
- Elements too close (< 0.3" gaps) or cards/sections nearly touching
- Uneven gaps (large empty area in one place, cramped in another)
- Insufficient margin from slide edges (< 0.5")
- Columns or similar elements not aligned consistently
- Low-contrast text (e.g., light gray text on cream-colored background)
- Low-contrast icons (e.g., dark icons on dark backgrounds without a contrasting circle)
- Text boxes too narrow causing excessive wrapping
- Leftover placeholder content
For each slide, list issues or areas of concern, even if minor.
Read and analyze these images:
1. /path/to/slide-01.jpg (Expected: [brief description])
2. /path/to/slide-02.jpg (Expected: [brief description])
Report ALL issues found, including minor ones.Verification Loop
1. Generate slides → Convert to images → Inspect 2. List issues found (if none found, look again more critically) 3. Fix issues 4. Re-verify affected slides — one fix often creates another problem 5. Repeat until a full pass reveals no new issues
Do not declare success until you've completed at least one fix-and-verify cycle.
---
Converting to Images
Convert presentations to individual slide images for visual inspection:
python scripts/office/soffice.py --headless --convert-to pdf output.pptx
pdftoppm -jpeg -r 150 output.pdf slideThis creates slide-01.jpg, slide-02.jpg, etc.
To re-render specific slides after fixes:
pdftoppm -jpeg -r 150 -f N -l N output.pdf slide-fixed---
Dependencies
pip install "markitdown[pptx]"- text extractionpip install Pillow- thumbnail gridsnpm install -g pptxgenjs- creating from scratch- LibreOffice (
soffice) - PDF conversion (auto-configured for sandboxed environments viascripts/office/soffice.py) - Poppler (
pdftoppm) - PDF to images
Editing Presentations
Template-Based Workflow
When using an existing presentation as a template:
1. Analyze existing slides:
python scripts/thumbnail.py template.pptx
python -m markitdown template.pptxReview thumbnails.jpg to see layouts, and markitdown output to see placeholder text.
2. Plan slide mapping: For each content section, choose a template slide.
⚠️ USE VARIED LAYOUTS — monotonous presentations are a common failure mode. Don't default to basic title + bullet slides. Actively seek out:
- Multi-column layouts (2-column, 3-column)
- Image + text combinations
- Full-bleed images with text overlay
- Quote or callout slides
- Section dividers
- Stat/number callouts
- Icon grids or icon + text rows
Avoid: Repeating the same text-heavy layout for every slide.
Match content type to layout style (e.g., key points → bullet slide, team info → multi-column, testimonials → quote slide).
3. Unpack: python scripts/office/unpack.py template.pptx unpacked/
4. Build presentation (do this yourself, not with subagents):
- Delete unwanted slides (remove from
<p:sldIdLst>) - Duplicate slides you want to reuse (
add_slide.py) - Reorder slides in
<p:sldIdLst> - Complete all structural changes before step 5
5. Edit content: Update text in each slide{N}.xml. Use subagents here if available — slides are separate XML files, so subagents can edit in parallel.
6. Clean: python scripts/clean.py unpacked/
7. Pack: python scripts/office/pack.py unpacked/ output.pptx --original template.pptx
---
Scripts
| Script | Purpose |
|---|---|
unpack.py | Extract and pretty-print PPTX |
add_slide.py | Duplicate slide or create from layout |
clean.py | Remove orphaned files |
pack.py | Repack with validation |
thumbnail.py | Create visual grid of slides |
unpack.py
python scripts/office/unpack.py input.pptx unpacked/Extracts PPTX, pretty-prints XML, escapes smart quotes.
add_slide.py
python scripts/add_slide.py unpacked/ slide2.xml # Duplicate slide
python scripts/add_slide.py unpacked/ slideLayout2.xml # From layoutPrints <p:sldId> to add to <p:sldIdLst> at desired position.
clean.py
python scripts/clean.py unpacked/Removes slides not in <p:sldIdLst>, unreferenced media, orphaned rels.
pack.py
python scripts/office/pack.py unpacked/ output.pptx --original input.pptxValidates, repairs, condenses XML, re-encodes smart quotes.
thumbnail.py
python scripts/thumbnail.py input.pptx [output_prefix] [--cols N]Creates thumbnails.jpg with slide filenames as labels. Default 3 columns, max 12 per grid.
Use for template analysis only (choosing layouts). For visual QA, use soffice + pdftoppm to create full-resolution individual slide images—see SKILL.md.
---
Slide Operations
Slide order is in ppt/presentation.xml → <p:sldIdLst>.
Reorder: Rearrange <p:sldId> elements.
Delete: Remove <p:sldId>, then run clean.py.
Add: Use add_slide.py. Never manually copy slide files—the script handles notes references, Content_Types.xml, and relationship IDs that manual copying misses.
---
Editing Content
Subagents: If available, use them here (after completing step 4). Each slide is a separate XML file, so subagents can edit in parallel. In your prompt to subagents, include:
- The slide file path(s) to edit
- "Use the Edit tool for all changes"
- The formatting rules and common pitfalls below
For each slide: 1. Read the slide's XML 2. Identify ALL placeholder content—text, images, charts, icons, captions 3. Replace each placeholder with final content
Use the Edit tool, not sed or Python scripts. The Edit tool forces specificity about what to replace and where, yielding better reliability.
Formatting Rules
- Bold all headers, subheadings, and inline labels: Use
b="1"on<a:rPr>. This includes: - Slide titles
- Section headers within a slide
- Inline labels like (e.g.: "Status:", "Description:") at the start of a line
- Never use unicode bullets (•): Use proper list formatting with
<a:buChar>or<a:buAutoNum> - Bullet consistency: Let bullets inherit from the layout. Only specify
<a:buChar>or<a:buNone>.
---
Common Pitfalls
Template Adaptation
When source content has fewer items than the template:
- Remove excess elements entirely (images, shapes, text boxes), don't just clear text
- Check for orphaned visuals after clearing text content
- Run visual QA to catch mismatched counts
When replacing text with different length content:
- Shorter replacements: Usually safe
- Longer replacements: May overflow or wrap unexpectedly
- Test with visual QA after text changes
- Consider truncating or splitting content to fit the template's design constraints
Template slots ≠ Source items: If template has 4 team members but source has 3 users, delete the 4th member's entire group (image + text boxes), not just the text.
Multi-Item Content
If source has multiple items (numbered lists, multiple sections), create separate <a:p> elements for each — never concatenate into one string.
❌ WRONG — all items in one paragraph:
<a:p>
<a:r><a:rPr .../><a:t>Step 1: Do the first thing. Step 2: Do the second thing.</a:t></a:r>
</a:p>✅ CORRECT — separate paragraphs with bold headers:
<a:p>
<a:pPr algn="l"><a:lnSpc><a:spcPts val="3919"/></a:lnSpc></a:pPr>
<a:r><a:rPr lang="en-US" sz="2799" b="1" .../><a:t>Step 1</a:t></a:r>
</a:p>
<a:p>
<a:pPr algn="l"><a:lnSpc><a:spcPts val="3919"/></a:lnSpc></a:pPr>
<a:r><a:rPr lang="en-US" sz="2799" .../><a:t>Do the first thing.</a:t></a:r>
</a:p>
<a:p>
<a:pPr algn="l"><a:lnSpc><a:spcPts val="3919"/></a:lnSpc></a:pPr>
<a:r><a:rPr lang="en-US" sz="2799" b="1" .../><a:t>Step 2</a:t></a:r>
</a:p>
<!-- continue pattern -->Copy <a:pPr> from the original paragraph to preserve line spacing. Use b="1" on headers.
Smart Quotes
Handled automatically by unpack/pack. But the Edit tool converts smart quotes to ASCII.
When adding new text with quotes, use XML entities:
<a:t>the “Agreement”</a:t>| Character | Name | Unicode | XML Entity |
|---|---|---|---|
“ | Left double quote | U+201C | “ |
” | Right double quote | U+201D | ” |
‘ | Left single quote | U+2018 | ‘ |
’ | Right single quote | U+2019 | ’ |
Other
- Whitespace: Use
xml:space="preserve"on<a:t>with leading/trailing spaces - XML parsing: Use
defusedxml.minidom, notxml.etree.ElementTree(corrupts namespaces)
© 2025 Anthropic, PBC. All rights reserved.
LICENSE: Use of these materials (including all code, prompts, assets, files,
and other components of this Skill) is governed by your agreement with
Anthropic regarding use of Anthropic's services. If no separate agreement
exists, use is governed by Anthropic's Consumer Terms of Service or
Commercial Terms of Service, as applicable:
https://www.anthropic.com/legal/consumer-terms
https://www.anthropic.com/legal/commercial-terms
Your applicable agreement is referred to as the "Agreement." "Services" are
as defined in the Agreement.
ADDITIONAL RESTRICTIONS: Notwithstanding anything in the Agreement to the
contrary, users may not:
- Extract these materials from the Services or retain copies of these
materials outside the Services
- Reproduce or copy these materials, except for temporary copies created
automatically during authorized use of the Services
- Create derivative works based on these materials
- Distribute, sublicense, or transfer these materials to any third party
- Make, offer to sell, sell, or import any inventions embodied in these
materials
- Reverse engineer, decompile, or disassemble these materials
The receipt, viewing, or possession of these materials does not convey or
imply any license or right beyond those expressly granted above.
Anthropic retains all right, title, and interest in these materials,
including all copyrights, patents, and other intellectual property rights.
PptxGenJS Tutorial
Setup & Basic Structure
const pptxgen = require("pptxgenjs");
let pres = new pptxgen();
pres.layout = 'LAYOUT_16x9'; // or 'LAYOUT_16x10', 'LAYOUT_4x3', 'LAYOUT_WIDE'
pres.author = 'Your Name';
pres.title = 'Presentation Title';
let slide = pres.addSlide();
slide.addText("Hello World!", { x: 0.5, y: 0.5, fontSize: 36, color: "363636" });
pres.writeFile({ fileName: "Presentation.pptx" });Layout Dimensions
Slide dimensions (coordinates in inches):
LAYOUT_16x9: 10" × 5.625" (default)LAYOUT_16x10: 10" × 6.25"LAYOUT_4x3: 10" × 7.5"LAYOUT_WIDE: 13.3" × 7.5"
---
Text & Formatting
// Basic text
slide.addText("Simple Text", {
x: 1, y: 1, w: 8, h: 2, fontSize: 24, fontFace: "Arial",
color: "363636", bold: true, align: "center", valign: "middle"
});
// Character spacing (use charSpacing, not letterSpacing which is silently ignored)
slide.addText("SPACED TEXT", { x: 1, y: 1, w: 8, h: 1, charSpacing: 6 });
// Rich text arrays
slide.addText([
{ text: "Bold ", options: { bold: true } },
{ text: "Italic ", options: { italic: true } }
], { x: 1, y: 3, w: 8, h: 1 });
// Multi-line text (requires breakLine: true)
slide.addText([
{ text: "Line 1", options: { breakLine: true } },
{ text: "Line 2", options: { breakLine: true } },
{ text: "Line 3" } // Last item doesn't need breakLine
], { x: 0.5, y: 0.5, w: 8, h: 2 });
// Text box margin (internal padding)
slide.addText("Title", {
x: 0.5, y: 0.3, w: 9, h: 0.6,
margin: 0 // Use 0 when aligning text with other elements like shapes or icons
});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.
---
Lists & Bullets
// ✅ CORRECT: Multiple bullets
slide.addText([
{ text: "First item", options: { bullet: true, breakLine: true } },
{ text: "Second item", options: { bullet: true, breakLine: true } },
{ text: "Third item", options: { bullet: true } }
], { x: 0.5, y: 0.5, w: 8, h: 3 });
// ❌ WRONG: Never use unicode bullets
slide.addText("• First item", { ... }); // Creates double bullets
// Sub-items and numbered lists
{ text: "Sub-item", options: { bullet: true, indentLevel: 1 } }
{ text: "First", options: { bullet: { type: "number" }, breakLine: true } }---
Shapes
slide.addShape(pres.shapes.RECTANGLE, {
x: 0.5, y: 0.8, w: 1.5, h: 3.0,
fill: { color: "FF0000" }, line: { color: "000000", width: 2 }
});
slide.addShape(pres.shapes.OVAL, { x: 4, y: 1, w: 2, h: 2, fill: { color: "0000FF" } });
slide.addShape(pres.shapes.LINE, {
x: 1, y: 3, w: 5, h: 0, line: { color: "FF0000", width: 3, dashType: "dash" }
});
// With transparency
slide.addShape(pres.shapes.RECTANGLE, {
x: 1, y: 1, w: 3, h: 2,
fill: { color: "0088CC", transparency: 50 }
});
// Rounded rectangle (rectRadius only works with ROUNDED_RECTANGLE, not RECTANGLE)
// ⚠️ Don't pair with rectangular accent overlays — they won't cover rounded corners. Use RECTANGLE instead.
slide.addShape(pres.shapes.ROUNDED_RECTANGLE, {
x: 1, y: 1, w: 3, h: 2,
fill: { color: "FFFFFF" }, rectRadius: 0.1
});
// With shadow
slide.addShape(pres.shapes.RECTANGLE, {
x: 1, y: 1, w: 3, h: 2,
fill: { color: "FFFFFF" },
shadow: { type: "outer", color: "000000", blur: 6, offset: 2, angle: 135, opacity: 0.15 }
});Shadow options:
| Property | Type | Range | Notes |
|---|---|---|---|
type | string | "outer", "inner" | |
color | string | 6-char hex (e.g. "000000") | No # prefix, no 8-char hex — see Common Pitfalls |
blur | number | 0-100 pt | |
offset | number | 0-200 pt | Must be non-negative — negative values corrupt the file |
angle | number | 0-359 degrees | Direction the shadow falls (135 = bottom-right, 270 = upward) |
opacity | number | 0.0-1.0 | Use this for transparency, never encode in color string |
To cast a shadow upward (e.g. on a footer bar), use angle: 270 with a positive offset — do not use a negative offset.
Note: Gradient fills are not natively supported. Use a gradient image as a background instead.
---
Images
Image Sources
// From file path
slide.addImage({ path: "images/chart.png", x: 1, y: 1, w: 5, h: 3 });
// From URL
slide.addImage({ path: "https://example.com/image.jpg", x: 1, y: 1, w: 5, h: 3 });
// From base64 (faster, no file I/O)
slide.addImage({ data: "image/png;base64,iVBORw0KGgo...", x: 1, y: 1, w: 5, h: 3 });Image Options
slide.addImage({
path: "image.png",
x: 1, y: 1, w: 5, h: 3,
rotate: 45, // 0-359 degrees
rounding: true, // Circular crop
transparency: 50, // 0-100
flipH: true, // Horizontal flip
flipV: false, // Vertical flip
altText: "Description", // Accessibility
hyperlink: { url: "https://example.com" }
});Image Sizing Modes
// Contain - fit inside, preserve ratio
{ sizing: { type: 'contain', w: 4, h: 3 } }
// Cover - fill area, preserve ratio (may crop)
{ sizing: { type: 'cover', w: 4, h: 3 } }
// Crop - cut specific portion
{ sizing: { type: 'crop', x: 0.5, y: 0.5, w: 2, h: 2 } }Calculate Dimensions (preserve aspect ratio)
const origWidth = 1978, origHeight = 923, maxHeight = 3.0;
const calcWidth = maxHeight * (origWidth / origHeight);
const centerX = (10 - calcWidth) / 2;
slide.addImage({ path: "image.png", x: centerX, y: 1.2, w: calcWidth, h: maxHeight });Supported Formats
- Standard: PNG, JPG, GIF (animated GIFs work in Microsoft 365)
- SVG: Works in modern PowerPoint/Microsoft 365
---
Icons
Use react-icons to generate SVG icons, then rasterize to PNG for universal compatibility.
Setup
const React = require("react");
const ReactDOMServer = require("react-dom/server");
const sharp = require("sharp");
const { FaCheckCircle, FaChartLine } = require("react-icons/fa");
function renderIconSvg(IconComponent, color = "#000000", size = 256) {
return ReactDOMServer.renderToStaticMarkup(
React.createElement(IconComponent, { color, size: String(size) })
);
}
async function iconToBase64Png(IconComponent, color, size = 256) {
const svg = renderIconSvg(IconComponent, color, size);
const pngBuffer = await sharp(Buffer.from(svg)).png().toBuffer();
return "image/png;base64," + pngBuffer.toString("base64");
}Add Icon to Slide
const iconData = await iconToBase64Png(FaCheckCircle, "#4472C4", 256);
slide.addImage({
data: iconData,
x: 1, y: 1, w: 0.5, h: 0.5 // Size in inches
});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).
Icon Libraries
Install: npm install -g react-icons react react-dom sharp
Popular icon sets in react-icons:
react-icons/fa- Font Awesomereact-icons/md- Material Designreact-icons/hi- Heroiconsreact-icons/bi- Bootstrap Icons
---
Slide Backgrounds
// Solid color
slide.background = { color: "F1F1F1" };
// Color with transparency
slide.background = { color: "FF3399", transparency: 50 };
// Image from URL
slide.background = { path: "https://example.com/bg.jpg" };
// Image from base64
slide.background = { data: "image/png;base64,iVBORw0KGgo..." };---
Tables
slide.addTable([
["Header 1", "Header 2"],
["Cell 1", "Cell 2"]
], {
x: 1, y: 1, w: 8, h: 2,
border: { pt: 1, color: "999999" }, fill: { color: "F1F1F1" }
});
// Advanced with merged cells
let tableData = [
[{ text: "Header", options: { fill: { color: "6699CC" }, color: "FFFFFF", bold: true } }, "Cell"],
[{ text: "Merged", options: { colspan: 2 } }]
];
slide.addTable(tableData, { x: 1, y: 3.5, w: 8, colW: [4, 4] });---
Charts
// Bar chart
slide.addChart(pres.charts.BAR, [{
name: "Sales", labels: ["Q1", "Q2", "Q3", "Q4"], values: [4500, 5500, 6200, 7100]
}], {
x: 0.5, y: 0.6, w: 6, h: 3, barDir: 'col',
showTitle: true, title: 'Quarterly Sales'
});
// Line chart
slide.addChart(pres.charts.LINE, [{
name: "Temp", labels: ["Jan", "Feb", "Mar"], values: [32, 35, 42]
}], { x: 0.5, y: 4, w: 6, h: 3, lineSize: 3, lineSmooth: true });
// Pie chart
slide.addChart(pres.charts.PIE, [{
name: "Share", labels: ["A", "B", "Other"], values: [35, 45, 20]
}], { x: 7, y: 1, w: 5, h: 4, showPercent: true });Better-Looking Charts
Default charts look dated. Apply these options for a modern, clean appearance:
slide.addChart(pres.charts.BAR, chartData, {
x: 0.5, y: 1, w: 9, h: 4, barDir: "col",
// Custom colors (match your presentation palette)
chartColors: ["0D9488", "14B8A6", "5EEAD4"],
// Clean background
chartArea: { fill: { color: "FFFFFF" }, roundedCorners: true },
// Muted axis labels
catAxisLabelColor: "64748B",
valAxisLabelColor: "64748B",
// Subtle grid (value axis only)
valGridLine: { color: "E2E8F0", size: 0.5 },
catGridLine: { style: "none" },
// Data labels on bars
showValue: true,
dataLabelPosition: "outEnd",
dataLabelColor: "1E293B",
// Hide legend for single series
showLegend: false,
});Key styling options:
chartColors: [...]- hex colors for series/segmentschartArea: { fill, border, roundedCorners }- chart backgroundcatGridLine/valGridLine: { color, style, size }- grid lines (style: "none"to hide)lineSmooth: true- curved lines (line charts)legendPos: "r"- legend position: "b", "t", "l", "r", "tr"
---
Slide Masters
pres.defineSlideMaster({
title: 'TITLE_SLIDE', background: { color: '283A5E' },
objects: [{
placeholder: { options: { name: 'title', type: 'title', x: 1, y: 2, w: 8, h: 2 } }
}]
});
let titleSlide = pres.addSlide({ masterName: "TITLE_SLIDE" });
titleSlide.addText("My Title", { placeholder: "title" });---
Common Pitfalls
⚠️ These issues cause file corruption, visual bugs, or broken output. Avoid them.
1. NEVER use "#" with hex colors - causes file corruption
color: "FF0000" // ✅ CORRECT
color: "#FF0000" // ❌ WRONG2. NEVER encode opacity in hex color strings - 8-char colors (e.g., "00000020") corrupt the file. Use the opacity property instead.
shadow: { type: "outer", blur: 6, offset: 2, color: "00000020" } // ❌ CORRUPTS FILE
shadow: { type: "outer", blur: 6, offset: 2, color: "000000", opacity: 0.12 } // ✅ CORRECT3. Use `bullet: true` - NEVER unicode symbols like "•" (creates double bullets)
4. Use `breakLine: true` between array items or text runs together
5. Avoid `lineSpacing` with bullets - causes excessive gaps; use paraSpaceAfter instead
6. Each presentation needs fresh instance - don't reuse pptxgen() objects
7. 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.
const shadow = { type: "outer", blur: 6, offset: 2, color: "000000", opacity: 0.15 };
slide.addShape(pres.shapes.RECTANGLE, { shadow, ... }); // ❌ second call gets already-converted values
slide.addShape(pres.shapes.RECTANGLE, { shadow, ... });
const makeShadow = () => ({ type: "outer", blur: 6, offset: 2, color: "000000", opacity: 0.15 });
slide.addShape(pres.shapes.RECTANGLE, { shadow: makeShadow(), ... }); // ✅ fresh object each time
slide.addShape(pres.shapes.RECTANGLE, { shadow: makeShadow(), ... });8. Don't use `ROUNDED_RECTANGLE` with accent borders - rectangular overlay bars won't cover rounded corners. Use RECTANGLE instead.
// ❌ WRONG: Accent bar doesn't cover rounded corners
slide.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: 1, y: 1, w: 3, h: 1.5, fill: { color: "FFFFFF" } });
slide.addShape(pres.shapes.RECTANGLE, { x: 1, y: 1, w: 0.08, h: 1.5, fill: { color: "0891B2" } });
// ✅ CORRECT: Use RECTANGLE for clean alignment
slide.addShape(pres.shapes.RECTANGLE, { x: 1, y: 1, w: 3, h: 1.5, fill: { color: "FFFFFF" } });
slide.addShape(pres.shapes.RECTANGLE, { x: 1, y: 1, w: 0.08, h: 1.5, fill: { color: "0891B2" } });---
Quick Reference
- Shapes: RECTANGLE, OVAL, LINE, ROUNDED_RECTANGLE
- Charts: BAR, LINE, PIE, DOUGHNUT, SCATTER, BUBBLE, RADAR
- Layouts: LAYOUT_16x9 (10"×5.625"), LAYOUT_16x10, LAYOUT_4x3, LAYOUT_WIDE
- Alignment: "left", "center", "right"
- Chart data labels: "outEnd", "inEnd", "center"
"""Add a new slide to an unpacked PPTX directory.
Usage: python add_slide.py <unpacked_dir> <source>
The source can be:
- A slide file (e.g., slide2.xml) - duplicates the slide
- A layout file (e.g., slideLayout2.xml) - creates from layout
Examples:
python add_slide.py unpacked/ slide2.xml
# Duplicates slide2, creates slide5.xml
python add_slide.py unpacked/ slideLayout2.xml
# Creates slide5.xml from slideLayout2.xml
To see available layouts: ls unpacked/ppt/slideLayouts/
Prints the <p:sldId> element to add to presentation.xml.
"""
import re
import shutil
import sys
from pathlib import Path
def get_next_slide_number(slides_dir: Path) -> int:
existing = [int(m.group(1)) for f in slides_dir.glob("slide*.xml")
if (m := re.match(r"slide(\d+)\.xml", f.name))]
return max(existing) + 1 if existing else 1
def create_slide_from_layout(unpacked_dir: Path, layout_file: str) -> None:
slides_dir = unpacked_dir / "ppt" / "slides"
rels_dir = slides_dir / "_rels"
layouts_dir = unpacked_dir / "ppt" / "slideLayouts"
layout_path = layouts_dir / layout_file
if not layout_path.exists():
print(f"Error: {layout_path} not found", file=sys.stderr)
sys.exit(1)
next_num = get_next_slide_number(slides_dir)
dest = f"slide{next_num}.xml"
dest_slide = slides_dir / dest
dest_rels = rels_dir / f"{dest}.rels"
slide_xml = '''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<p:sld xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main">
<p:cSld>
<p:spTree>
<p:nvGrpSpPr>
<p:cNvPr id="1" name=""/>
<p:cNvGrpSpPr/>
<p:nvPr/>
</p:nvGrpSpPr>
<p:grpSpPr>
<a:xfrm>
<a:off x="0" y="0"/>
<a:ext cx="0" cy="0"/>
<a:chOff x="0" y="0"/>
<a:chExt cx="0" cy="0"/>
</a:xfrm>
</p:grpSpPr>
</p:spTree>
</p:cSld>
<p:clrMapOvr>
<a:masterClrMapping/>
</p:clrMapOvr>
</p:sld>'''
dest_slide.write_text(slide_xml, encoding="utf-8")
rels_dir.mkdir(exist_ok=True)
rels_xml = f'''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout" Target="../slideLayouts/{layout_file}"/>
</Relationships>'''
dest_rels.write_text(rels_xml, encoding="utf-8")
_add_to_content_types(unpacked_dir, dest)
rid = _add_to_presentation_rels(unpacked_dir, dest)
next_slide_id = _get_next_slide_id(unpacked_dir)
print(f"Created {dest} from {layout_file}")
print(f'Add to presentation.xml <p:sldIdLst>: <p:sldId id="{next_slide_id}" r:id="{rid}"/>')
def duplicate_slide(unpacked_dir: Path, source: str) -> None:
slides_dir = unpacked_dir / "ppt" / "slides"
rels_dir = slides_dir / "_rels"
source_slide = slides_dir / source
if not source_slide.exists():
print(f"Error: {source_slide} not found", file=sys.stderr)
sys.exit(1)
next_num = get_next_slide_number(slides_dir)
dest = f"slide{next_num}.xml"
dest_slide = slides_dir / dest
source_rels = rels_dir / f"{source}.rels"
dest_rels = rels_dir / f"{dest}.rels"
shutil.copy2(source_slide, dest_slide)
if source_rels.exists():
shutil.copy2(source_rels, dest_rels)
rels_content = dest_rels.read_text(encoding="utf-8")
rels_content = re.sub(
r'\s*<Relationship[^>]*Type="[^"]*notesSlide"[^>]*/>\s*',
"\n",
rels_content,
)
dest_rels.write_text(rels_content, encoding="utf-8")
_add_to_content_types(unpacked_dir, dest)
rid = _add_to_presentation_rels(unpacked_dir, dest)
next_slide_id = _get_next_slide_id(unpacked_dir)
print(f"Created {dest} from {source}")
print(f'Add to presentation.xml <p:sldIdLst>: <p:sldId id="{next_slide_id}" r:id="{rid}"/>')
def _add_to_content_types(unpacked_dir: Path, dest: str) -> None:
content_types_path = unpacked_dir / "[Content_Types].xml"
content_types = content_types_path.read_text(encoding="utf-8")
new_override = f'<Override PartName="/ppt/slides/{dest}" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slide+xml"/>'
if f"/ppt/slides/{dest}" not in content_types:
content_types = content_types.replace("</Types>", f" {new_override}\n</Types>")
content_types_path.write_text(content_types, encoding="utf-8")
def _add_to_presentation_rels(unpacked_dir: Path, dest: str) -> str:
pres_rels_path = unpacked_dir / "ppt" / "_rels" / "presentation.xml.rels"
pres_rels = pres_rels_path.read_text(encoding="utf-8")
rids = [int(m) for m in re.findall(r'Id="rId(\d+)"', pres_rels)]
next_rid = max(rids) + 1 if rids else 1
rid = f"rId{next_rid}"
new_rel = f'<Relationship Id="{rid}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide" Target="slides/{dest}"/>'
if f"slides/{dest}" not in pres_rels:
pres_rels = pres_rels.replace("</Relationships>", f" {new_rel}\n</Relationships>")
pres_rels_path.write_text(pres_rels, encoding="utf-8")
return rid
def _get_next_slide_id(unpacked_dir: Path) -> int:
pres_path = unpacked_dir / "ppt" / "presentation.xml"
pres_content = pres_path.read_text(encoding="utf-8")
slide_ids = [int(m) for m in re.findall(r'<p:sldId[^>]*id="(\d+)"', pres_content)]
return max(slide_ids) + 1 if slide_ids else 256
def parse_source(source: str) -> tuple[str, str | None]:
if source.startswith("slideLayout") and source.endswith(".xml"):
return ("layout", source)
return ("slide", None)
if __name__ == "__main__":
if len(sys.argv) != 3:
print("Usage: python add_slide.py <unpacked_dir> <source>", file=sys.stderr)
print("", file=sys.stderr)
print("Source can be:", file=sys.stderr)
print(" slide2.xml - duplicate an existing slide", file=sys.stderr)
print(" slideLayout2.xml - create from a layout template", file=sys.stderr)
print("", file=sys.stderr)
print("To see available layouts: ls <unpacked_dir>/ppt/slideLayouts/", file=sys.stderr)
sys.exit(1)
unpacked_dir = Path(sys.argv[1])
source = sys.argv[2]
if not unpacked_dir.exists():
print(f"Error: {unpacked_dir} not found", file=sys.stderr)
sys.exit(1)
source_type, layout_file = parse_source(source)
if source_type == "layout" and layout_file is not None:
create_slide_from_layout(unpacked_dir, layout_file)
else:
duplicate_slide(unpacked_dir, source)
"""Remove unreferenced files from an unpacked PPTX directory.
Usage: python clean.py <unpacked_dir>
Example:
python clean.py unpacked/
This script removes:
- Orphaned slides (not in sldIdLst) and their relationships
- [trash] directory (unreferenced files)
- Orphaned .rels files for deleted resources
- Unreferenced media, embeddings, charts, diagrams, drawings, ink files
- Unreferenced theme files
- Unreferenced notes slides
- Content-Type overrides for deleted files
"""
import sys
from pathlib import Path
import defusedxml.minidom
import re
def get_slides_in_sldidlst(unpacked_dir: Path) -> set[str]:
pres_path = unpacked_dir / "ppt" / "presentation.xml"
pres_rels_path = unpacked_dir / "ppt" / "_rels" / "presentation.xml.rels"
if not pres_path.exists() or not pres_rels_path.exists():
return set()
rels_dom = defusedxml.minidom.parse(str(pres_rels_path))
rid_to_slide = {}
for rel in rels_dom.getElementsByTagName("Relationship"):
rid = rel.getAttribute("Id")
target = rel.getAttribute("Target")
rel_type = rel.getAttribute("Type")
if "slide" in rel_type and target.startswith("slides/"):
rid_to_slide[rid] = target.replace("slides/", "")
pres_content = pres_path.read_text(encoding="utf-8")
referenced_rids = set(re.findall(r'<p:sldId[^>]*r:id="([^"]+)"', pres_content))
return {rid_to_slide[rid] for rid in referenced_rids if rid in rid_to_slide}
def remove_orphaned_slides(unpacked_dir: Path) -> list[str]:
slides_dir = unpacked_dir / "ppt" / "slides"
slides_rels_dir = slides_dir / "_rels"
pres_rels_path = unpacked_dir / "ppt" / "_rels" / "presentation.xml.rels"
if not slides_dir.exists():
return []
referenced_slides = get_slides_in_sldidlst(unpacked_dir)
removed = []
for slide_file in slides_dir.glob("slide*.xml"):
if slide_file.name not in referenced_slides:
rel_path = slide_file.relative_to(unpacked_dir)
slide_file.unlink()
removed.append(str(rel_path))
rels_file = slides_rels_dir / f"{slide_file.name}.rels"
if rels_file.exists():
rels_file.unlink()
removed.append(str(rels_file.relative_to(unpacked_dir)))
if removed and pres_rels_path.exists():
rels_dom = defusedxml.minidom.parse(str(pres_rels_path))
changed = False
for rel in list(rels_dom.getElementsByTagName("Relationship")):
target = rel.getAttribute("Target")
if target.startswith("slides/"):
slide_name = target.replace("slides/", "")
if slide_name not in referenced_slides:
if rel.parentNode:
rel.parentNode.removeChild(rel)
changed = True
if changed:
with open(pres_rels_path, "wb") as f:
f.write(rels_dom.toxml(encoding="utf-8"))
return removed
def remove_trash_directory(unpacked_dir: Path) -> list[str]:
trash_dir = unpacked_dir / "[trash]"
removed = []
if trash_dir.exists() and trash_dir.is_dir():
for file_path in trash_dir.iterdir():
if file_path.is_file():
rel_path = file_path.relative_to(unpacked_dir)
removed.append(str(rel_path))
file_path.unlink()
trash_dir.rmdir()
return removed
def get_slide_referenced_files(unpacked_dir: Path) -> set:
referenced = set()
slides_rels_dir = unpacked_dir / "ppt" / "slides" / "_rels"
if not slides_rels_dir.exists():
return referenced
for rels_file in slides_rels_dir.glob("*.rels"):
dom = defusedxml.minidom.parse(str(rels_file))
for rel in dom.getElementsByTagName("Relationship"):
target = rel.getAttribute("Target")
if not target:
continue
target_path = (rels_file.parent.parent / target).resolve()
try:
referenced.add(target_path.relative_to(unpacked_dir.resolve()))
except ValueError:
pass
return referenced
def remove_orphaned_rels_files(unpacked_dir: Path) -> list[str]:
resource_dirs = ["charts", "diagrams", "drawings"]
removed = []
slide_referenced = get_slide_referenced_files(unpacked_dir)
for dir_name in resource_dirs:
rels_dir = unpacked_dir / "ppt" / dir_name / "_rels"
if not rels_dir.exists():
continue
for rels_file in rels_dir.glob("*.rels"):
resource_file = rels_dir.parent / rels_file.name.replace(".rels", "")
try:
resource_rel_path = resource_file.resolve().relative_to(unpacked_dir.resolve())
except ValueError:
continue
if not resource_file.exists() or resource_rel_path not in slide_referenced:
rels_file.unlink()
rel_path = rels_file.relative_to(unpacked_dir)
removed.append(str(rel_path))
return removed
def get_referenced_files(unpacked_dir: Path) -> set:
referenced = set()
for rels_file in unpacked_dir.rglob("*.rels"):
dom = defusedxml.minidom.parse(str(rels_file))
for rel in dom.getElementsByTagName("Relationship"):
target = rel.getAttribute("Target")
if not target:
continue
target_path = (rels_file.parent.parent / target).resolve()
try:
referenced.add(target_path.relative_to(unpacked_dir.resolve()))
except ValueError:
pass
return referenced
def remove_orphaned_files(unpacked_dir: Path, referenced: set) -> list[str]:
resource_dirs = ["media", "embeddings", "charts", "diagrams", "tags", "drawings", "ink"]
removed = []
for dir_name in resource_dirs:
dir_path = unpacked_dir / "ppt" / dir_name
if not dir_path.exists():
continue
for file_path in dir_path.glob("*"):
if not file_path.is_file():
continue
rel_path = file_path.relative_to(unpacked_dir)
if rel_path not in referenced:
file_path.unlink()
removed.append(str(rel_path))
theme_dir = unpacked_dir / "ppt" / "theme"
if theme_dir.exists():
for file_path in theme_dir.glob("theme*.xml"):
rel_path = file_path.relative_to(unpacked_dir)
if rel_path not in referenced:
file_path.unlink()
removed.append(str(rel_path))
theme_rels = theme_dir / "_rels" / f"{file_path.name}.rels"
if theme_rels.exists():
theme_rels.unlink()
removed.append(str(theme_rels.relative_to(unpacked_dir)))
notes_dir = unpacked_dir / "ppt" / "notesSlides"
if notes_dir.exists():
for file_path in notes_dir.glob("*.xml"):
if not file_path.is_file():
continue
rel_path = file_path.relative_to(unpacked_dir)
if rel_path not in referenced:
file_path.unlink()
removed.append(str(rel_path))
notes_rels_dir = notes_dir / "_rels"
if notes_rels_dir.exists():
for file_path in notes_rels_dir.glob("*.rels"):
notes_file = notes_dir / file_path.name.replace(".rels", "")
if not notes_file.exists():
file_path.unlink()
removed.append(str(file_path.relative_to(unpacked_dir)))
return removed
def update_content_types(unpacked_dir: Path, removed_files: list[str]) -> None:
ct_path = unpacked_dir / "[Content_Types].xml"
if not ct_path.exists():
return
dom = defusedxml.minidom.parse(str(ct_path))
changed = False
for override in list(dom.getElementsByTagName("Override")):
part_name = override.getAttribute("PartName").lstrip("/")
if part_name in removed_files:
if override.parentNode:
override.parentNode.removeChild(override)
changed = True
if changed:
with open(ct_path, "wb") as f:
f.write(dom.toxml(encoding="utf-8"))
def clean_unused_files(unpacked_dir: Path) -> list[str]:
all_removed = []
slides_removed = remove_orphaned_slides(unpacked_dir)
all_removed.extend(slides_removed)
trash_removed = remove_trash_directory(unpacked_dir)
all_removed.extend(trash_removed)
while True:
removed_rels = remove_orphaned_rels_files(unpacked_dir)
referenced = get_referenced_files(unpacked_dir)
removed_files = remove_orphaned_files(unpacked_dir, referenced)
total_removed = removed_rels + removed_files
if not total_removed:
break
all_removed.extend(total_removed)
if all_removed:
update_content_types(unpacked_dir, all_removed)
return all_removed
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: python clean.py <unpacked_dir>", file=sys.stderr)
print("Example: python clean.py unpacked/", file=sys.stderr)
sys.exit(1)
unpacked_dir = Path(sys.argv[1])
if not unpacked_dir.exists():
print(f"Error: {unpacked_dir} not found", file=sys.stderr)
sys.exit(1)
removed = clean_unused_files(unpacked_dir)
if removed:
print(f"Removed {len(removed)} unreferenced files:")
for f in removed:
print(f" {f}")
else:
print("No unreferenced files found")
"""Merge adjacent runs with identical formatting in DOCX.
Merges adjacent <w:r> elements that have identical <w:rPr> properties.
Works on runs in paragraphs and inside tracked changes (<w:ins>, <w:del>).
Also:
- Removes rsid attributes from runs (revision metadata that doesn't affect rendering)
- Removes proofErr elements (spell/grammar markers that block merging)
"""
from pathlib import Path
import defusedxml.minidom
def merge_runs(input_dir: str) -> tuple[int, str]:
doc_xml = Path(input_dir) / "word" / "document.xml"
if not doc_xml.exists():
return 0, f"Error: {doc_xml} not found"
try:
dom = defusedxml.minidom.parseString(doc_xml.read_text(encoding="utf-8"))
root = dom.documentElement
_remove_elements(root, "proofErr")
_strip_run_rsid_attrs(root)
containers = {run.parentNode for run in _find_elements(root, "r")}
merge_count = 0
for container in containers:
merge_count += _merge_runs_in(container)
doc_xml.write_bytes(dom.toxml(encoding="UTF-8"))
return merge_count, f"Merged {merge_count} runs"
except Exception as e:
return 0, f"Error: {e}"
def _find_elements(root, tag: str) -> list:
results = []
def traverse(node):
if node.nodeType == node.ELEMENT_NODE:
name = node.localName or node.tagName
if name == tag or name.endswith(f":{tag}"):
results.append(node)
for child in node.childNodes:
traverse(child)
traverse(root)
return results
def _get_child(parent, tag: str):
for child in parent.childNodes:
if child.nodeType == child.ELEMENT_NODE:
name = child.localName or child.tagName
if name == tag or name.endswith(f":{tag}"):
return child
return None
def _get_children(parent, tag: str) -> list:
results = []
for child in parent.childNodes:
if child.nodeType == child.ELEMENT_NODE:
name = child.localName or child.tagName
if name == tag or name.endswith(f":{tag}"):
results.append(child)
return results
def _is_adjacent(elem1, elem2) -> bool:
node = elem1.nextSibling
while node:
if node == elem2:
return True
if node.nodeType == node.ELEMENT_NODE:
return False
if node.nodeType == node.TEXT_NODE and node.data.strip():
return False
node = node.nextSibling
return False
def _remove_elements(root, tag: str):
for elem in _find_elements(root, tag):
if elem.parentNode:
elem.parentNode.removeChild(elem)
def _strip_run_rsid_attrs(root):
for run in _find_elements(root, "r"):
for attr in list(run.attributes.values()):
if "rsid" in attr.name.lower():
run.removeAttribute(attr.name)
def _merge_runs_in(container) -> int:
merge_count = 0
run = _first_child_run(container)
while run:
while True:
next_elem = _next_element_sibling(run)
if next_elem and _is_run(next_elem) and _can_merge(run, next_elem):
_merge_run_content(run, next_elem)
container.removeChild(next_elem)
merge_count += 1
else:
break
_consolidate_text(run)
run = _next_sibling_run(run)
return merge_count
def _first_child_run(container):
for child in container.childNodes:
if child.nodeType == child.ELEMENT_NODE and _is_run(child):
return child
return None
def _next_element_sibling(node):
sibling = node.nextSibling
while sibling:
if sibling.nodeType == sibling.ELEMENT_NODE:
return sibling
sibling = sibling.nextSibling
return None
def _next_sibling_run(node):
sibling = node.nextSibling
while sibling:
if sibling.nodeType == sibling.ELEMENT_NODE:
if _is_run(sibling):
return sibling
sibling = sibling.nextSibling
return None
def _is_run(node) -> bool:
name = node.localName or node.tagName
return name == "r" or name.endswith(":r")
def _can_merge(run1, run2) -> bool:
rpr1 = _get_child(run1, "rPr")
rpr2 = _get_child(run2, "rPr")
if (rpr1 is None) != (rpr2 is None):
return False
if rpr1 is None:
return True
return rpr1.toxml() == rpr2.toxml()
def _merge_run_content(target, source):
for child in list(source.childNodes):
if child.nodeType == child.ELEMENT_NODE:
name = child.localName or child.tagName
if name != "rPr" and not name.endswith(":rPr"):
target.appendChild(child)
def _consolidate_text(run):
t_elements = _get_children(run, "t")
for i in range(len(t_elements) - 1, 0, -1):
curr, prev = t_elements[i], t_elements[i - 1]
if _is_adjacent(prev, curr):
prev_text = prev.firstChild.data if prev.firstChild else ""
curr_text = curr.firstChild.data if curr.firstChild else ""
merged = prev_text + curr_text
if prev.firstChild:
prev.firstChild.data = merged
else:
prev.appendChild(run.ownerDocument.createTextNode(merged))
if merged.startswith(" ") or merged.endswith(" "):
prev.setAttribute("xml:space", "preserve")
elif prev.hasAttribute("xml:space"):
prev.removeAttribute("xml:space")
run.removeChild(curr)
"""Simplify tracked changes by merging adjacent w:ins or w:del elements.
Merges adjacent <w:ins> elements from the same author into a single element.
Same for <w:del> elements. This makes heavily-redlined documents easier to
work with by reducing the number of tracked change wrappers.
Rules:
- Only merges w:ins with w:ins, w:del with w:del (same element type)
- Only merges if same author (ignores timestamp differences)
- Only merges if truly adjacent (only whitespace between them)
"""
import xml.etree.ElementTree as ET
import zipfile
from pathlib import Path
import defusedxml.minidom
WORD_NS = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
def simplify_redlines(input_dir: str) -> tuple[int, str]:
doc_xml = Path(input_dir) / "word" / "document.xml"
if not doc_xml.exists():
return 0, f"Error: {doc_xml} not found"
try:
dom = defusedxml.minidom.parseString(doc_xml.read_text(encoding="utf-8"))
root = dom.documentElement
merge_count = 0
containers = _find_elements(root, "p") + _find_elements(root, "tc")
for container in containers:
merge_count += _merge_tracked_changes_in(container, "ins")
merge_count += _merge_tracked_changes_in(container, "del")
doc_xml.write_bytes(dom.toxml(encoding="UTF-8"))
return merge_count, f"Simplified {merge_count} tracked changes"
except Exception as e:
return 0, f"Error: {e}"
def _merge_tracked_changes_in(container, tag: str) -> int:
merge_count = 0
tracked = [
child
for child in container.childNodes
if child.nodeType == child.ELEMENT_NODE and _is_element(child, tag)
]
if len(tracked) < 2:
return 0
i = 0
while i < len(tracked) - 1:
curr = tracked[i]
next_elem = tracked[i + 1]
if _can_merge_tracked(curr, next_elem):
_merge_tracked_content(curr, next_elem)
container.removeChild(next_elem)
tracked.pop(i + 1)
merge_count += 1
else:
i += 1
return merge_count
def _is_element(node, tag: str) -> bool:
name = node.localName or node.tagName
return name == tag or name.endswith(f":{tag}")
def _get_author(elem) -> str:
author = elem.getAttribute("w:author")
if not author:
for attr in elem.attributes.values():
if attr.localName == "author" or attr.name.endswith(":author"):
return attr.value
return author
def _can_merge_tracked(elem1, elem2) -> bool:
if _get_author(elem1) != _get_author(elem2):
return False
node = elem1.nextSibling
while node and node != elem2:
if node.nodeType == node.ELEMENT_NODE:
return False
if node.nodeType == node.TEXT_NODE and node.data.strip():
return False
node = node.nextSibling
return True
def _merge_tracked_content(target, source):
while source.firstChild:
child = source.firstChild
source.removeChild(child)
target.appendChild(child)
def _find_elements(root, tag: str) -> list:
results = []
def traverse(node):
if node.nodeType == node.ELEMENT_NODE:
name = node.localName or node.tagName
if name == tag or name.endswith(f":{tag}"):
results.append(node)
for child in node.childNodes:
traverse(child)
traverse(root)
return results
def get_tracked_change_authors(doc_xml_path: Path) -> dict[str, int]:
if not doc_xml_path.exists():
return {}
try:
tree = ET.parse(doc_xml_path)
root = tree.getroot()
except ET.ParseError:
return {}
namespaces = {"w": WORD_NS}
author_attr = f"{{{WORD_NS}}}author"
authors: dict[str, int] = {}
for tag in ["ins", "del"]:
for elem in root.findall(f".//w:{tag}", namespaces):
author = elem.get(author_attr)
if author:
authors[author] = authors.get(author, 0) + 1
return authors
def _get_authors_from_docx(docx_path: Path) -> dict[str, int]:
try:
with zipfile.ZipFile(docx_path, "r") as zf:
if "word/document.xml" not in zf.namelist():
return {}
with zf.open("word/document.xml") as f:
tree = ET.parse(f)
root = tree.getroot()
namespaces = {"w": WORD_NS}
author_attr = f"{{{WORD_NS}}}author"
authors: dict[str, int] = {}
for tag in ["ins", "del"]:
for elem in root.findall(f".//w:{tag}", namespaces):
author = elem.get(author_attr)
if author:
authors[author] = authors.get(author, 0) + 1
return authors
except (zipfile.BadZipFile, ET.ParseError):
return {}
def infer_author(modified_dir: Path, original_docx: Path, default: str = "Claude") -> str:
modified_xml = modified_dir / "word" / "document.xml"
modified_authors = get_tracked_change_authors(modified_xml)
if not modified_authors:
return default
original_authors = _get_authors_from_docx(original_docx)
new_changes: dict[str, int] = {}
for author, count in modified_authors.items():
original_count = original_authors.get(author, 0)
diff = count - original_count
if diff > 0:
new_changes[author] = diff
if not new_changes:
return default
if len(new_changes) == 1:
return next(iter(new_changes))
raise ValueError(
f"Multiple authors added new changes: {new_changes}. "
"Cannot infer which author to validate."
)
"""Pack a directory into a DOCX, PPTX, or XLSX file.
Validates with auto-repair, condenses XML formatting, and creates the Office file.
Usage:
python pack.py <input_directory> <output_file> [--original <file>] [--validate true|false]
Examples:
python pack.py unpacked/ output.docx --original input.docx
python pack.py unpacked/ output.pptx --validate false
"""
import argparse
import sys
import shutil
import tempfile
import zipfile
from pathlib import Path
import defusedxml.minidom
from validators import DOCXSchemaValidator, PPTXSchemaValidator, RedliningValidator
def pack(
input_directory: str,
output_file: str,
original_file: str | None = None,
validate: bool = True,
infer_author_func=None,
) -> tuple[None, str]:
input_dir = Path(input_directory)
output_path = Path(output_file)
suffix = output_path.suffix.lower()
if not input_dir.is_dir():
return None, f"Error: {input_dir} is not a directory"
if suffix not in {".docx", ".pptx", ".xlsx"}:
return None, f"Error: {output_file} must be a .docx, .pptx, or .xlsx file"
if validate and original_file:
original_path = Path(original_file)
if original_path.exists():
success, output = _run_validation(
input_dir, original_path, suffix, infer_author_func
)
if output:
print(output)
if not success:
return None, f"Error: Validation failed for {input_dir}"
with tempfile.TemporaryDirectory() as temp_dir:
temp_content_dir = Path(temp_dir) / "content"
shutil.copytree(input_dir, temp_content_dir)
for pattern in ["*.xml", "*.rels"]:
for xml_file in temp_content_dir.rglob(pattern):
_condense_xml(xml_file)
output_path.parent.mkdir(parents=True, exist_ok=True)
with zipfile.ZipFile(output_path, "w", zipfile.ZIP_DEFLATED) as zf:
for f in temp_content_dir.rglob("*"):
if f.is_file():
zf.write(f, f.relative_to(temp_content_dir))
return None, f"Successfully packed {input_dir} to {output_file}"
def _run_validation(
unpacked_dir: Path,
original_file: Path,
suffix: str,
infer_author_func=None,
) -> tuple[bool, str | None]:
output_lines = []
validators = []
if suffix == ".docx":
author = "Claude"
if infer_author_func:
try:
author = infer_author_func(unpacked_dir, original_file)
except ValueError as e:
print(f"Warning: {e} Using default author 'Claude'.", file=sys.stderr)
validators = [
DOCXSchemaValidator(unpacked_dir, original_file),
RedliningValidator(unpacked_dir, original_file, author=author),
]
elif suffix == ".pptx":
validators = [PPTXSchemaValidator(unpacked_dir, original_file)]
if not validators:
return True, None
total_repairs = sum(v.repair() for v in validators)
if total_repairs:
output_lines.append(f"Auto-repaired {total_repairs} issue(s)")
success = all(v.validate() for v in validators)
if success:
output_lines.append("All validations PASSED!")
return success, "\n".join(output_lines) if output_lines else None
def _condense_xml(xml_file: Path) -> None:
try:
with open(xml_file, encoding="utf-8") as f:
dom = defusedxml.minidom.parse(f)
for element in dom.getElementsByTagName("*"):
if element.tagName.endswith(":t"):
continue
for child in list(element.childNodes):
if (
child.nodeType == child.TEXT_NODE
and child.nodeValue
and child.nodeValue.strip() == ""
) or child.nodeType == child.COMMENT_NODE:
element.removeChild(child)
xml_file.write_bytes(dom.toxml(encoding="UTF-8"))
except Exception as e:
print(f"ERROR: Failed to parse {xml_file.name}: {e}", file=sys.stderr)
raise
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Pack a directory into a DOCX, PPTX, or XLSX file"
)
parser.add_argument("input_directory", help="Unpacked Office document directory")
parser.add_argument("output_file", help="Output Office file (.docx/.pptx/.xlsx)")
parser.add_argument(
"--original",
help="Original file for validation comparison",
)
parser.add_argument(
"--validate",
type=lambda x: x.lower() == "true",
default=True,
metavar="true|false",
help="Run validation with auto-repair (default: true)",
)
args = parser.parse_args()
_, message = pack(
args.input_directory,
args.output_file,
original_file=args.original,
validate=args.validate,
)
print(message)
if "Error" in message:
sys.exit(1)
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xs:schema xmlns="http://schemas.openxmlformats.org/package/2006/content-types"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://schemas.openxmlformats.org/package/2006/content-types"
elementFormDefault="qualified" attributeFormDefault="unqualified" blockDefault="#all">
<xs:element name="Types" type="CT_Types"/>
<xs:element name="Default" type="CT_Default"/>
<xs:element name="Override" type="CT_Override"/>
<xs:complexType name="CT_Types">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="Default"/>
<xs:element ref="Override"/>
</xs:choice>
</xs:complexType>
<xs:complexType name="CT_Default">
<xs:attribute name="Extension" type="ST_Extension" use="required"/>
<xs:attribute name="ContentType" type="ST_ContentType" use="required"/>
</xs:complexType>
<xs:complexType name="CT_Override">
<xs:attribute name="ContentType" type="ST_ContentType" use="required"/>
<xs:attribute name="PartName" type="xs:anyURI" use="required"/>
</xs:complexType>
<xs:simpleType name="ST_ContentType">
<xs:restriction base="xs:string">
<xs:pattern
value="(((([\p{IsBasicLatin}-[\p{Cc}\(\)<>@,;:\\"/\[\]\?=\{\}\s\t]])+))/((([\p{IsBasicLatin}-[\p{Cc}\(\)<>@,;:\\"/\[\]\?=\{\}\s\t]])+))((\s+)*;(\s+)*(((([\p{IsBasicLatin}-[\p{Cc}\(\)<>@,;:\\"/\[\]\?=\{\}\s\t]])+))=((([\p{IsBasicLatin}-[\p{Cc}\(\)<>@,;:\\"/\[\]\?=\{\}\s\t]])+)|("(([\p{IsLatin-1Supplement}\p{IsBasicLatin}-[\p{Cc}"\n\r]]|(\s+))|(\\[\p{IsBasicLatin}]))*"))))*)"
/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="ST_Extension">
<xs:restriction base="xs:string">
<xs:pattern
value="([!$&'\(\)\*\+,:=]|(%[0-9a-fA-F][0-9a-fA-F])|[:@]|[a-zA-Z0-9\-_~])+"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://schemas.openxmlformats.org/package/2006/metadata/core-properties"
xmlns="http://schemas.openxmlformats.org/package/2006/metadata/core-properties"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:dcterms="http://purl.org/dc/terms/" elementFormDefault="qualified" blockDefault="#all">
<xs:import namespace="http://purl.org/dc/elements/1.1/"
schemaLocation="http://dublincore.org/schemas/xmls/qdc/2003/04/02/dc.xsd"/>
<xs:import namespace="http://purl.org/dc/terms/"
schemaLocation="http://dublincore.org/schemas/xmls/qdc/2003/04/02/dcterms.xsd"/>
<xs:import id="xml" namespace="http://www.w3.org/XML/1998/namespace"/>
<xs:element name="coreProperties" type="CT_CoreProperties"/>
<xs:complexType name="CT_CoreProperties">
<xs:all>
<xs:element name="category" minOccurs="0" maxOccurs="1" type="xs:string"/>
<xs:element name="contentStatus" minOccurs="0" maxOccurs="1" type="xs:string"/>
<xs:element ref="dcterms:created" minOccurs="0" maxOccurs="1"/>
<xs:element ref="dc:creator" minOccurs="0" maxOccurs="1"/>
<xs:element ref="dc:description" minOccurs="0" maxOccurs="1"/>
<xs:element ref="dc:identifier" minOccurs="0" maxOccurs="1"/>
<xs:element name="keywords" minOccurs="0" maxOccurs="1" type="CT_Keywords"/>
<xs:element ref="dc:language" minOccurs="0" maxOccurs="1"/>
<xs:element name="lastModifiedBy" minOccurs="0" maxOccurs="1" type="xs:string"/>
<xs:element name="lastPrinted" minOccurs="0" maxOccurs="1" type="xs:dateTime"/>
<xs:element ref="dcterms:modified" minOccurs="0" maxOccurs="1"/>
<xs:element name="revision" minOccurs="0" maxOccurs="1" type="xs:string"/>
<xs:element ref="dc:subject" minOccurs="0" maxOccurs="1"/>
<xs:element ref="dc:title" minOccurs="0" maxOccurs="1"/>
<xs:element name="version" minOccurs="0" maxOccurs="1" type="xs:string"/>
</xs:all>
</xs:complexType>
<xs:complexType name="CT_Keywords" mixed="true">
<xs:sequence>
<xs:element name="value" minOccurs="0" maxOccurs="unbounded" type="CT_Keyword"/>
</xs:sequence>
<xs:attribute ref="xml:lang" use="optional"/>
</xs:complexType>
<xs:complexType name="CT_Keyword">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute ref="xml:lang" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:schema>
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://schemas.openxmlformats.org/package/2006/digital-signature"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://schemas.openxmlformats.org/package/2006/digital-signature"
elementFormDefault="qualified" attributeFormDefault="unqualified" blockDefault="#all">
<xsd:element name="SignatureTime" type="CT_SignatureTime"/>
<xsd:element name="RelationshipReference" type="CT_RelationshipReference"/>
<xsd:element name="RelationshipsGroupReference" type="CT_RelationshipsGroupReference"/>
<xsd:complexType name="CT_SignatureTime">
<xsd:sequence>
<xsd:element name="Format" type="ST_Format"/>
<xsd:element name="Value" type="ST_Value"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_RelationshipReference">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="SourceId" type="xsd:string" use="required"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
<xsd:complexType name="CT_RelationshipsGroupReference">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="SourceType" type="xsd:anyURI" use="required"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
<xsd:simpleType name="ST_Format">
<xsd:restriction base="xsd:string">
<xsd:pattern
value="(YYYY)|(YYYY-MM)|(YYYY-MM-DD)|(YYYY-MM-DDThh:mmTZD)|(YYYY-MM-DDThh:mm:ssTZD)|(YYYY-MM-DDThh:mm:ss.sTZD)"
/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_Value">
<xsd:restriction base="xsd:string">
<xsd:pattern
value="(([0-9][0-9][0-9][0-9]))|(([0-9][0-9][0-9][0-9])-((0[1-9])|(1(0|1|2))))|(([0-9][0-9][0-9][0-9])-((0[1-9])|(1(0|1|2)))-((0[1-9])|(1[0-9])|(2[0-9])|(3(0|1))))|(([0-9][0-9][0-9][0-9])-((0[1-9])|(1(0|1|2)))-((0[1-9])|(1[0-9])|(2[0-9])|(3(0|1)))T((0[0-9])|(1[0-9])|(2(0|1|2|3))):((0[0-9])|(1[0-9])|(2[0-9])|(3[0-9])|(4[0-9])|(5[0-9]))(((\+|-)((0[0-9])|(1[0-9])|(2(0|1|2|3))):((0[0-9])|(1[0-9])|(2[0-9])|(3[0-9])|(4[0-9])|(5[0-9])))|Z))|(([0-9][0-9][0-9][0-9])-((0[1-9])|(1(0|1|2)))-((0[1-9])|(1[0-9])|(2[0-9])|(3(0|1)))T((0[0-9])|(1[0-9])|(2(0|1|2|3))):((0[0-9])|(1[0-9])|(2[0-9])|(3[0-9])|(4[0-9])|(5[0-9])):((0[0-9])|(1[0-9])|(2[0-9])|(3[0-9])|(4[0-9])|(5[0-9]))(((\+|-)((0[0-9])|(1[0-9])|(2(0|1|2|3))):((0[0-9])|(1[0-9])|(2[0-9])|(3[0-9])|(4[0-9])|(5[0-9])))|Z))|(([0-9][0-9][0-9][0-9])-((0[1-9])|(1(0|1|2)))-((0[1-9])|(1[0-9])|(2[0-9])|(3(0|1)))T((0[0-9])|(1[0-9])|(2(0|1|2|3))):((0[0-9])|(1[0-9])|(2[0-9])|(3[0-9])|(4[0-9])|(5[0-9])):(((0[0-9])|(1[0-9])|(2[0-9])|(3[0-9])|(4[0-9])|(5[0-9]))\.[0-9])(((\+|-)((0[0-9])|(1[0-9])|(2(0|1|2|3))):((0[0-9])|(1[0-9])|(2[0-9])|(3[0-9])|(4[0-9])|(5[0-9])))|Z))"
/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://schemas.openxmlformats.org/package/2006/relationships"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://schemas.openxmlformats.org/package/2006/relationships"
elementFormDefault="qualified" attributeFormDefault="unqualified" blockDefault="#all">
<xsd:element name="Relationships" type="CT_Relationships"/>
<xsd:element name="Relationship" type="CT_Relationship"/>
<xsd:complexType name="CT_Relationships">
<xsd:sequence>
<xsd:element ref="Relationship" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Relationship">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="TargetMode" type="ST_TargetMode" use="optional"/>
<xsd:attribute name="Target" type="xsd:anyURI" use="required"/>
<xsd:attribute name="Type" type="xsd:anyURI" use="required"/>
<xsd:attribute name="Id" type="xsd:ID" use="required"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
<xsd:simpleType name="ST_TargetMode">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="External"/>
<xsd:enumeration value="Internal"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
xmlns="http://schemas.openxmlformats.org/drawingml/2006/chartDrawing"
targetNamespace="http://schemas.openxmlformats.org/drawingml/2006/chartDrawing"
elementFormDefault="qualified">
<xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/main"
schemaLocation="dml-main.xsd"/>
<xsd:complexType name="CT_ShapeNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
<xsd:element name="cNvSpPr" type="a:CT_NonVisualDrawingShapeProps" minOccurs="1" maxOccurs="1"
/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Shape">
<xsd:sequence>
<xsd:element name="nvSpPr" type="CT_ShapeNonVisual" minOccurs="1" maxOccurs="1"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="1" maxOccurs="1"/>
<xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0" maxOccurs="1"/>
<xsd:element name="txBody" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="macro" type="xsd:string" use="optional"/>
<xsd:attribute name="textlink" type="xsd:string" use="optional"/>
<xsd:attribute name="fLocksText" type="xsd:boolean" use="optional" default="true"/>
<xsd:attribute name="fPublished" type="xsd:boolean" use="optional" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_ConnectorNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
<xsd:element name="cNvCxnSpPr" type="a:CT_NonVisualConnectorProperties" minOccurs="1"
maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Connector">
<xsd:sequence>
<xsd:element name="nvCxnSpPr" type="CT_ConnectorNonVisual" minOccurs="1" maxOccurs="1"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="1" maxOccurs="1"/>
<xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="macro" type="xsd:string" use="optional"/>
<xsd:attribute name="fPublished" type="xsd:boolean" use="optional" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_PictureNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
<xsd:element name="cNvPicPr" type="a:CT_NonVisualPictureProperties" minOccurs="1"
maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Picture">
<xsd:sequence>
<xsd:element name="nvPicPr" type="CT_PictureNonVisual" minOccurs="1" maxOccurs="1"/>
<xsd:element name="blipFill" type="a:CT_BlipFillProperties" minOccurs="1" maxOccurs="1"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="1" maxOccurs="1"/>
<xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="macro" type="xsd:string" use="optional" default=""/>
<xsd:attribute name="fPublished" type="xsd:boolean" use="optional" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_GraphicFrameNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
<xsd:element name="cNvGraphicFramePr" type="a:CT_NonVisualGraphicFrameProperties"
minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_GraphicFrame">
<xsd:sequence>
<xsd:element name="nvGraphicFramePr" type="CT_GraphicFrameNonVisual" minOccurs="1"
maxOccurs="1"/>
<xsd:element name="xfrm" type="a:CT_Transform2D" minOccurs="1" maxOccurs="1"/>
<xsd:element ref="a:graphic" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="macro" type="xsd:string" use="optional"/>
<xsd:attribute name="fPublished" type="xsd:boolean" use="optional" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_GroupShapeNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
<xsd:element name="cNvGrpSpPr" type="a:CT_NonVisualGroupDrawingShapeProps" minOccurs="1"
maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_GroupShape">
<xsd:sequence>
<xsd:element name="nvGrpSpPr" type="CT_GroupShapeNonVisual" minOccurs="1" maxOccurs="1"/>
<xsd:element name="grpSpPr" type="a:CT_GroupShapeProperties" minOccurs="1" maxOccurs="1"/>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="sp" type="CT_Shape"/>
<xsd:element name="grpSp" type="CT_GroupShape"/>
<xsd:element name="graphicFrame" type="CT_GraphicFrame"/>
<xsd:element name="cxnSp" type="CT_Connector"/>
<xsd:element name="pic" type="CT_Picture"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:group name="EG_ObjectChoices">
<xsd:sequence>
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element name="sp" type="CT_Shape"/>
<xsd:element name="grpSp" type="CT_GroupShape"/>
<xsd:element name="graphicFrame" type="CT_GraphicFrame"/>
<xsd:element name="cxnSp" type="CT_Connector"/>
<xsd:element name="pic" type="CT_Picture"/>
</xsd:choice>
</xsd:sequence>
</xsd:group>
<xsd:simpleType name="ST_MarkerCoordinate">
<xsd:restriction base="xsd:double">
<xsd:minInclusive value="0.0"/>
<xsd:maxInclusive value="1.0"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_Marker">
<xsd:sequence>
<xsd:element name="x" type="ST_MarkerCoordinate" minOccurs="1" maxOccurs="1"/>
<xsd:element name="y" type="ST_MarkerCoordinate" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_RelSizeAnchor">
<xsd:sequence>
<xsd:element name="from" type="CT_Marker"/>
<xsd:element name="to" type="CT_Marker"/>
<xsd:group ref="EG_ObjectChoices"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_AbsSizeAnchor">
<xsd:sequence>
<xsd:element name="from" type="CT_Marker"/>
<xsd:element name="ext" type="a:CT_PositiveSize2D"/>
<xsd:group ref="EG_ObjectChoices"/>
</xsd:sequence>
</xsd:complexType>
<xsd:group name="EG_Anchor">
<xsd:choice>
<xsd:element name="relSizeAnchor" type="CT_RelSizeAnchor"/>
<xsd:element name="absSizeAnchor" type="CT_AbsSizeAnchor"/>
</xsd:choice>
</xsd:group>
<xsd:complexType name="CT_Drawing">
<xsd:sequence>
<xsd:group ref="EG_Anchor" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.openxmlformats.org/drawingml/2006/diagram"
xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns:s="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes"
targetNamespace="http://schemas.openxmlformats.org/drawingml/2006/diagram"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
schemaLocation="shared-relationshipReference.xsd"/>
<xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/main"
schemaLocation="dml-main.xsd"/>
<xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes"
schemaLocation="shared-commonSimpleTypes.xsd"/>
<xsd:complexType name="CT_CTName">
<xsd:attribute name="lang" type="xsd:string" use="optional" default=""/>
<xsd:attribute name="val" type="xsd:string" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_CTDescription">
<xsd:attribute name="lang" type="xsd:string" use="optional" default=""/>
<xsd:attribute name="val" type="xsd:string" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_CTCategory">
<xsd:attribute name="type" type="xsd:anyURI" use="required"/>
<xsd:attribute name="pri" type="xsd:unsignedInt" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_CTCategories">
<xsd:sequence minOccurs="0" maxOccurs="unbounded">
<xsd:element name="cat" type="CT_CTCategory" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:simpleType name="ST_ClrAppMethod">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="span"/>
<xsd:enumeration value="cycle"/>
<xsd:enumeration value="repeat"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_HueDir">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="cw"/>
<xsd:enumeration value="ccw"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_Colors">
<xsd:sequence>
<xsd:group ref="a:EG_ColorChoice" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="meth" type="ST_ClrAppMethod" use="optional" default="span"/>
<xsd:attribute name="hueDir" type="ST_HueDir" use="optional" default="cw"/>
</xsd:complexType>
<xsd:complexType name="CT_CTStyleLabel">
<xsd:sequence>
<xsd:element name="fillClrLst" type="CT_Colors" minOccurs="0" maxOccurs="1"/>
<xsd:element name="linClrLst" type="CT_Colors" minOccurs="0" maxOccurs="1"/>
<xsd:element name="effectClrLst" type="CT_Colors" minOccurs="0" maxOccurs="1"/>
<xsd:element name="txLinClrLst" type="CT_Colors" minOccurs="0" maxOccurs="1"/>
<xsd:element name="txFillClrLst" type="CT_Colors" minOccurs="0" maxOccurs="1"/>
<xsd:element name="txEffectClrLst" type="CT_Colors" minOccurs="0" maxOccurs="1"/>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_ColorTransform">
<xsd:sequence>
<xsd:element name="title" type="CT_CTName" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="desc" type="CT_CTDescription" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="catLst" type="CT_CTCategories" minOccurs="0"/>
<xsd:element name="styleLbl" type="CT_CTStyleLabel" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="uniqueId" type="xsd:string" use="optional" default=""/>
<xsd:attribute name="minVer" type="xsd:string" use="optional"/>
</xsd:complexType>
<xsd:element name="colorsDef" type="CT_ColorTransform"/>
<xsd:complexType name="CT_ColorTransformHeader">
<xsd:sequence>
<xsd:element name="title" type="CT_CTName" minOccurs="1" maxOccurs="unbounded"/>
<xsd:element name="desc" type="CT_CTDescription" minOccurs="1" maxOccurs="unbounded"/>
<xsd:element name="catLst" type="CT_CTCategories" minOccurs="0"/>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="uniqueId" type="xsd:string" use="required"/>
<xsd:attribute name="minVer" type="xsd:string" use="optional"/>
<xsd:attribute name="resId" type="xsd:int" use="optional" default="0"/>
</xsd:complexType>
<xsd:element name="colorsDefHdr" type="CT_ColorTransformHeader"/>
<xsd:complexType name="CT_ColorTransformHeaderLst">
<xsd:sequence>
<xsd:element name="colorsDefHdr" type="CT_ColorTransformHeader" minOccurs="0"
maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="colorsDefHdrLst" type="CT_ColorTransformHeaderLst"/>
<xsd:simpleType name="ST_PtType">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="node"/>
<xsd:enumeration value="asst"/>
<xsd:enumeration value="doc"/>
<xsd:enumeration value="pres"/>
<xsd:enumeration value="parTrans"/>
<xsd:enumeration value="sibTrans"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_Pt">
<xsd:sequence>
<xsd:element name="prSet" type="CT_ElemPropSet" minOccurs="0" maxOccurs="1"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/>
<xsd:element name="t" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="modelId" type="ST_ModelId" use="required"/>
<xsd:attribute name="type" type="ST_PtType" use="optional" default="node"/>
<xsd:attribute name="cxnId" type="ST_ModelId" use="optional" default="0"/>
</xsd:complexType>
<xsd:complexType name="CT_PtList">
<xsd:sequence>
<xsd:element name="pt" type="CT_Pt" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:simpleType name="ST_CxnType">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="parOf"/>
<xsd:enumeration value="presOf"/>
<xsd:enumeration value="presParOf"/>
<xsd:enumeration value="unknownRelationship"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_Cxn">
<xsd:sequence>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="modelId" type="ST_ModelId" use="required"/>
<xsd:attribute name="type" type="ST_CxnType" use="optional" default="parOf"/>
<xsd:attribute name="srcId" type="ST_ModelId" use="required"/>
<xsd:attribute name="destId" type="ST_ModelId" use="required"/>
<xsd:attribute name="srcOrd" type="xsd:unsignedInt" use="required"/>
<xsd:attribute name="destOrd" type="xsd:unsignedInt" use="required"/>
<xsd:attribute name="parTransId" type="ST_ModelId" use="optional" default="0"/>
<xsd:attribute name="sibTransId" type="ST_ModelId" use="optional" default="0"/>
<xsd:attribute name="presId" type="xsd:string" use="optional" default=""/>
</xsd:complexType>
<xsd:complexType name="CT_CxnList">
<xsd:sequence>
<xsd:element name="cxn" type="CT_Cxn" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_DataModel">
<xsd:sequence>
<xsd:element name="ptLst" type="CT_PtList"/>
<xsd:element name="cxnLst" type="CT_CxnList" minOccurs="0" maxOccurs="1"/>
<xsd:element name="bg" type="a:CT_BackgroundFormatting" minOccurs="0"/>
<xsd:element name="whole" type="a:CT_WholeE2oFormatting" minOccurs="0"/>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="dataModel" type="CT_DataModel"/>
<xsd:attributeGroup name="AG_IteratorAttributes">
<xsd:attribute name="axis" type="ST_AxisTypes" use="optional" default="none"/>
<xsd:attribute name="ptType" type="ST_ElementTypes" use="optional" default="all"/>
<xsd:attribute name="hideLastTrans" type="ST_Booleans" use="optional" default="true"/>
<xsd:attribute name="st" type="ST_Ints" use="optional" default="1"/>
<xsd:attribute name="cnt" type="ST_UnsignedInts" use="optional" default="0"/>
<xsd:attribute name="step" type="ST_Ints" use="optional" default="1"/>
</xsd:attributeGroup>
<xsd:attributeGroup name="AG_ConstraintAttributes">
<xsd:attribute name="type" type="ST_ConstraintType" use="required"/>
<xsd:attribute name="for" type="ST_ConstraintRelationship" use="optional" default="self"/>
<xsd:attribute name="forName" type="xsd:string" use="optional" default=""/>
<xsd:attribute name="ptType" type="ST_ElementType" use="optional" default="all"/>
</xsd:attributeGroup>
<xsd:attributeGroup name="AG_ConstraintRefAttributes">
<xsd:attribute name="refType" type="ST_ConstraintType" use="optional" default="none"/>
<xsd:attribute name="refFor" type="ST_ConstraintRelationship" use="optional" default="self"/>
<xsd:attribute name="refForName" type="xsd:string" use="optional" default=""/>
<xsd:attribute name="refPtType" type="ST_ElementType" use="optional" default="all"/>
</xsd:attributeGroup>
<xsd:complexType name="CT_Constraint">
<xsd:sequence>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attributeGroup ref="AG_ConstraintAttributes"/>
<xsd:attributeGroup ref="AG_ConstraintRefAttributes"/>
<xsd:attribute name="op" type="ST_BoolOperator" use="optional" default="none"/>
<xsd:attribute name="val" type="xsd:double" use="optional" default="0"/>
<xsd:attribute name="fact" type="xsd:double" use="optional" default="1"/>
</xsd:complexType>
<xsd:complexType name="CT_Constraints">
<xsd:sequence>
<xsd:element name="constr" type="CT_Constraint" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_NumericRule">
<xsd:sequence>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attributeGroup ref="AG_ConstraintAttributes"/>
<xsd:attribute name="val" type="xsd:double" use="optional" default="NaN"/>
<xsd:attribute name="fact" type="xsd:double" use="optional" default="NaN"/>
<xsd:attribute name="max" type="xsd:double" use="optional" default="NaN"/>
</xsd:complexType>
<xsd:complexType name="CT_Rules">
<xsd:sequence>
<xsd:element name="rule" type="CT_NumericRule" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_PresentationOf">
<xsd:sequence>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attributeGroup ref="AG_IteratorAttributes"/>
</xsd:complexType>
<xsd:simpleType name="ST_LayoutShapeType" final="restriction">
<xsd:union memberTypes="a:ST_ShapeType ST_OutputShapeType"/>
</xsd:simpleType>
<xsd:simpleType name="ST_Index1">
<xsd:restriction base="xsd:unsignedInt">
<xsd:minInclusive value="1"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_Adj">
<xsd:attribute name="idx" type="ST_Index1" use="required"/>
<xsd:attribute name="val" type="xsd:double" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_AdjLst">
<xsd:sequence>
<xsd:element name="adj" type="CT_Adj" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Shape">
<xsd:sequence>
<xsd:element name="adjLst" type="CT_AdjLst" minOccurs="0" maxOccurs="1"/>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="rot" type="xsd:double" use="optional" default="0"/>
<xsd:attribute name="type" type="ST_LayoutShapeType" use="optional" default="none"/>
<xsd:attribute ref="r:blip" use="optional"/>
<xsd:attribute name="zOrderOff" type="xsd:int" use="optional" default="0"/>
<xsd:attribute name="hideGeom" type="xsd:boolean" use="optional" default="false"/>
<xsd:attribute name="lkTxEntry" type="xsd:boolean" use="optional" default="false"/>
<xsd:attribute name="blipPhldr" type="xsd:boolean" use="optional" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_Parameter">
<xsd:attribute name="type" type="ST_ParameterId" use="required"/>
<xsd:attribute name="val" type="ST_ParameterVal" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_Algorithm">
<xsd:sequence>
<xsd:element name="param" type="CT_Parameter" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="type" type="ST_AlgorithmType" use="required"/>
<xsd:attribute name="rev" type="xsd:unsignedInt" use="optional" default="0"/>
</xsd:complexType>
<xsd:complexType name="CT_LayoutNode">
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="alg" type="CT_Algorithm" minOccurs="0" maxOccurs="1"/>
<xsd:element name="shape" type="CT_Shape" minOccurs="0" maxOccurs="1"/>
<xsd:element name="presOf" type="CT_PresentationOf" minOccurs="0" maxOccurs="1"/>
<xsd:element name="constrLst" type="CT_Constraints" minOccurs="0" maxOccurs="1"/>
<xsd:element name="ruleLst" type="CT_Rules" minOccurs="0" maxOccurs="1"/>
<xsd:element name="varLst" type="CT_LayoutVariablePropertySet" minOccurs="0" maxOccurs="1"/>
<xsd:element name="forEach" type="CT_ForEach"/>
<xsd:element name="layoutNode" type="CT_LayoutNode"/>
<xsd:element name="choose" type="CT_Choose"/>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:choice>
<xsd:attribute name="name" type="xsd:string" use="optional" default=""/>
<xsd:attribute name="styleLbl" type="xsd:string" use="optional" default=""/>
<xsd:attribute name="chOrder" type="ST_ChildOrderType" use="optional" default="b"/>
<xsd:attribute name="moveWith" type="xsd:string" use="optional" default=""/>
</xsd:complexType>
<xsd:complexType name="CT_ForEach">
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="alg" type="CT_Algorithm" minOccurs="0" maxOccurs="1"/>
<xsd:element name="shape" type="CT_Shape" minOccurs="0" maxOccurs="1"/>
<xsd:element name="presOf" type="CT_PresentationOf" minOccurs="0" maxOccurs="1"/>
<xsd:element name="constrLst" type="CT_Constraints" minOccurs="0" maxOccurs="1"/>
<xsd:element name="ruleLst" type="CT_Rules" minOccurs="0" maxOccurs="1"/>
<xsd:element name="forEach" type="CT_ForEach"/>
<xsd:element name="layoutNode" type="CT_LayoutNode"/>
<xsd:element name="choose" type="CT_Choose"/>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:choice>
<xsd:attribute name="name" type="xsd:string" use="optional" default=""/>
<xsd:attribute name="ref" type="xsd:string" use="optional" default=""/>
<xsd:attributeGroup ref="AG_IteratorAttributes"/>
</xsd:complexType>
<xsd:complexType name="CT_When">
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="alg" type="CT_Algorithm" minOccurs="0" maxOccurs="1"/>
<xsd:element name="shape" type="CT_Shape" minOccurs="0" maxOccurs="1"/>
<xsd:element name="presOf" type="CT_PresentationOf" minOccurs="0" maxOccurs="1"/>
<xsd:element name="constrLst" type="CT_Constraints" minOccurs="0" maxOccurs="1"/>
<xsd:element name="ruleLst" type="CT_Rules" minOccurs="0" maxOccurs="1"/>
<xsd:element name="forEach" type="CT_ForEach"/>
<xsd:element name="layoutNode" type="CT_LayoutNode"/>
<xsd:element name="choose" type="CT_Choose"/>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:choice>
<xsd:attribute name="name" type="xsd:string" use="optional" default=""/>
<xsd:attributeGroup ref="AG_IteratorAttributes"/>
<xsd:attribute name="func" type="ST_FunctionType" use="required"/>
<xsd:attribute name="arg" type="ST_FunctionArgument" use="optional" default="none"/>
<xsd:attribute name="op" type="ST_FunctionOperator" use="required"/>
<xsd:attribute name="val" type="ST_FunctionValue" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_Otherwise">
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="alg" type="CT_Algorithm" minOccurs="0" maxOccurs="1"/>
<xsd:element name="shape" type="CT_Shape" minOccurs="0" maxOccurs="1"/>
<xsd:element name="presOf" type="CT_PresentationOf" minOccurs="0" maxOccurs="1"/>
<xsd:element name="constrLst" type="CT_Constraints" minOccurs="0" maxOccurs="1"/>
<xsd:element name="ruleLst" type="CT_Rules" minOccurs="0" maxOccurs="1"/>
<xsd:element name="forEach" type="CT_ForEach"/>
<xsd:element name="layoutNode" type="CT_LayoutNode"/>
<xsd:element name="choose" type="CT_Choose"/>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:choice>
<xsd:attribute name="name" type="xsd:string" use="optional" default=""/>
</xsd:complexType>
<xsd:complexType name="CT_Choose">
<xsd:sequence>
<xsd:element name="if" type="CT_When" maxOccurs="unbounded"/>
<xsd:element name="else" type="CT_Otherwise" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="optional" default=""/>
</xsd:complexType>
<xsd:complexType name="CT_SampleData">
<xsd:sequence>
<xsd:element name="dataModel" type="CT_DataModel" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="useDef" type="xsd:boolean" use="optional" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_Category">
<xsd:attribute name="type" type="xsd:anyURI" use="required"/>
<xsd:attribute name="pri" type="xsd:unsignedInt" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_Categories">
<xsd:sequence>
<xsd:element name="cat" type="CT_Category" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Name">
<xsd:attribute name="lang" type="xsd:string" use="optional" default=""/>
<xsd:attribute name="val" type="xsd:string" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_Description">
<xsd:attribute name="lang" type="xsd:string" use="optional" default=""/>
<xsd:attribute name="val" type="xsd:string" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_DiagramDefinition">
<xsd:sequence>
<xsd:element name="title" type="CT_Name" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="desc" type="CT_Description" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="catLst" type="CT_Categories" minOccurs="0"/>
<xsd:element name="sampData" type="CT_SampleData" minOccurs="0"/>
<xsd:element name="styleData" type="CT_SampleData" minOccurs="0"/>
<xsd:element name="clrData" type="CT_SampleData" minOccurs="0"/>
<xsd:element name="layoutNode" type="CT_LayoutNode"/>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="uniqueId" type="xsd:string" use="optional" default=""/>
<xsd:attribute name="minVer" type="xsd:string" use="optional"/>
<xsd:attribute name="defStyle" type="xsd:string" use="optional" default=""/>
</xsd:complexType>
<xsd:element name="layoutDef" type="CT_DiagramDefinition"/>
<xsd:complexType name="CT_DiagramDefinitionHeader">
<xsd:sequence>
<xsd:element name="title" type="CT_Name" minOccurs="1" maxOccurs="unbounded"/>
<xsd:element name="desc" type="CT_Description" minOccurs="1" maxOccurs="unbounded"/>
<xsd:element name="catLst" type="CT_Categories" minOccurs="0"/>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="uniqueId" type="xsd:string" use="required"/>
<xsd:attribute name="minVer" type="xsd:string" use="optional"/>
<xsd:attribute name="defStyle" type="xsd:string" use="optional" default=""/>
<xsd:attribute name="resId" type="xsd:int" use="optional" default="0"/>
</xsd:complexType>
<xsd:element name="layoutDefHdr" type="CT_DiagramDefinitionHeader"/>
<xsd:complexType name="CT_DiagramDefinitionHeaderLst">
<xsd:sequence>
<xsd:element name="layoutDefHdr" type="CT_DiagramDefinitionHeader" minOccurs="0"
maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="layoutDefHdrLst" type="CT_DiagramDefinitionHeaderLst"/>
<xsd:complexType name="CT_RelIds">
<xsd:attribute ref="r:dm" use="required"/>
<xsd:attribute ref="r:lo" use="required"/>
<xsd:attribute ref="r:qs" use="required"/>
<xsd:attribute ref="r:cs" use="required"/>
</xsd:complexType>
<xsd:element name="relIds" type="CT_RelIds"/>
<xsd:simpleType name="ST_ParameterVal">
<xsd:union
memberTypes="ST_DiagramHorizontalAlignment ST_VerticalAlignment ST_ChildDirection ST_ChildAlignment ST_SecondaryChildAlignment ST_LinearDirection ST_SecondaryLinearDirection ST_StartingElement ST_BendPoint ST_ConnectorRouting ST_ArrowheadStyle ST_ConnectorDimension ST_RotationPath ST_CenterShapeMapping ST_NodeHorizontalAlignment ST_NodeVerticalAlignment ST_FallbackDimension ST_TextDirection ST_PyramidAccentPosition ST_PyramidAccentTextMargin ST_TextBlockDirection ST_TextAnchorHorizontal ST_TextAnchorVertical ST_DiagramTextAlignment ST_AutoTextRotation ST_GrowDirection ST_FlowDirection ST_ContinueDirection ST_Breakpoint ST_Offset ST_HierarchyAlignment xsd:int xsd:double xsd:boolean xsd:string ST_ConnectorPoint"
/>
</xsd:simpleType>
<xsd:simpleType name="ST_ModelId">
<xsd:union memberTypes="xsd:int s:ST_Guid"/>
</xsd:simpleType>
<xsd:simpleType name="ST_PrSetCustVal">
<xsd:union memberTypes="s:ST_Percentage xsd:int"/>
</xsd:simpleType>
<xsd:complexType name="CT_ElemPropSet">
<xsd:sequence>
<xsd:element name="presLayoutVars" type="CT_LayoutVariablePropertySet" minOccurs="0"
maxOccurs="1"/>
<xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="presAssocID" type="ST_ModelId" use="optional"/>
<xsd:attribute name="presName" type="xsd:string" use="optional"/>
<xsd:attribute name="presStyleLbl" type="xsd:string" use="optional"/>
<xsd:attribute name="presStyleIdx" type="xsd:int" use="optional"/>
<xsd:attribute name="presStyleCnt" type="xsd:int" use="optional"/>
<xsd:attribute name="loTypeId" type="xsd:string" use="optional"/>
<xsd:attribute name="loCatId" type="xsd:string" use="optional"/>
<xsd:attribute name="qsTypeId" type="xsd:string" use="optional"/>
<xsd:attribute name="qsCatId" type="xsd:string" use="optional"/>
<xsd:attribute name="csTypeId" type="xsd:string" use="optional"/>
<xsd:attribute name="csCatId" type="xsd:string" use="optional"/>
<xsd:attribute name="coherent3DOff" type="xsd:boolean" use="optional"/>
<xsd:attribute name="phldrT" type="xsd:string" use="optional"/>
<xsd:attribute name="phldr" type="xsd:boolean" use="optional"/>
<xsd:attribute name="custAng" type="xsd:int" use="optional"/>
<xsd:attribute name="custFlipVert" type="xsd:boolean" use="optional"/>
<xsd:attribute name="custFlipHor" type="xsd:boolean" use="optional"/>
<xsd:attribute name="custSzX" type="xsd:int" use="optional"/>
<xsd:attribute name="custSzY" type="xsd:int" use="optional"/>
<xsd:attribute name="custScaleX" type="ST_PrSetCustVal" use="optional"/>
<xsd:attribute name="custScaleY" type="ST_PrSetCustVal" use="optional"/>
<xsd:attribute name="custT" type="xsd:boolean" use="optional"/>
<xsd:attribute name="custLinFactX" type="ST_PrSetCustVal" use="optional"/>
<xsd:attribute name="custLinFactY" type="ST_PrSetCustVal" use="optional"/>
<xsd:attribute name="custLinFactNeighborX" type="ST_PrSetCustVal" use="optional"/>
<xsd:attribute name="custLinFactNeighborY" type="ST_PrSetCustVal" use="optional"/>
<xsd:attribute name="custRadScaleRad" type="ST_PrSetCustVal" use="optional"/>
<xsd:attribute name="custRadScaleInc" type="ST_PrSetCustVal" use="optional"/>
</xsd:complexType>
<xsd:simpleType name="ST_Direction" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="norm"/>
<xsd:enumeration value="rev"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_HierBranchStyle" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="l"/>
<xsd:enumeration value="r"/>
<xsd:enumeration value="hang"/>
<xsd:enumeration value="std"/>
<xsd:enumeration value="init"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_AnimOneStr" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="none"/>
<xsd:enumeration value="one"/>
<xsd:enumeration value="branch"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_AnimLvlStr" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="none"/>
<xsd:enumeration value="lvl"/>
<xsd:enumeration value="ctr"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_OrgChart">
<xsd:attribute name="val" type="xsd:boolean" default="false" use="optional"/>
</xsd:complexType>
<xsd:simpleType name="ST_NodeCount">
<xsd:restriction base="xsd:int">
<xsd:minInclusive value="-1"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_ChildMax">
<xsd:attribute name="val" type="ST_NodeCount" default="-1" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_ChildPref">
<xsd:attribute name="val" type="ST_NodeCount" default="-1" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_BulletEnabled">
<xsd:attribute name="val" type="xsd:boolean" default="false" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_Direction">
<xsd:attribute name="val" type="ST_Direction" default="norm" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_HierBranchStyle">
<xsd:attribute name="val" type="ST_HierBranchStyle" default="std" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_AnimOne">
<xsd:attribute name="val" type="ST_AnimOneStr" default="one" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_AnimLvl">
<xsd:attribute name="val" type="ST_AnimLvlStr" default="none" use="optional"/>
</xsd:complexType>
<xsd:simpleType name="ST_ResizeHandlesStr" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="exact"/>
<xsd:enumeration value="rel"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_ResizeHandles">
<xsd:attribute name="val" type="ST_ResizeHandlesStr" default="rel" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_LayoutVariablePropertySet">
<xsd:sequence>
<xsd:element name="orgChart" type="CT_OrgChart" minOccurs="0" maxOccurs="1"/>
<xsd:element name="chMax" type="CT_ChildMax" minOccurs="0" maxOccurs="1"/>
<xsd:element name="chPref" type="CT_ChildPref" minOccurs="0" maxOccurs="1"/>
<xsd:element name="bulletEnabled" type="CT_BulletEnabled" minOccurs="0" maxOccurs="1"/>
<xsd:element name="dir" type="CT_Direction" minOccurs="0" maxOccurs="1"/>
<xsd:element name="hierBranch" type="CT_HierBranchStyle" minOccurs="0" maxOccurs="1"/>
<xsd:element name="animOne" type="CT_AnimOne" minOccurs="0" maxOccurs="1"/>
<xsd:element name="animLvl" type="CT_AnimLvl" minOccurs="0" maxOccurs="1"/>
<xsd:element name="resizeHandles" type="CT_ResizeHandles" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_SDName">
<xsd:attribute name="lang" type="xsd:string" use="optional" default=""/>
<xsd:attribute name="val" type="xsd:string" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_SDDescription">
<xsd:attribute name="lang" type="xsd:string" use="optional" default=""/>
<xsd:attribute name="val" type="xsd:string" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_SDCategory">
<xsd:attribute name="type" type="xsd:anyURI" use="required"/>
<xsd:attribute name="pri" type="xsd:unsignedInt" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_SDCategories">
<xsd:sequence minOccurs="0" maxOccurs="unbounded">
<xsd:element name="cat" type="CT_SDCategory" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_TextProps">
<xsd:sequence>
<xsd:group ref="a:EG_Text3D" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_StyleLabel">
<xsd:sequence>
<xsd:element name="scene3d" type="a:CT_Scene3D" minOccurs="0" maxOccurs="1"/>
<xsd:element name="sp3d" type="a:CT_Shape3D" minOccurs="0" maxOccurs="1"/>
<xsd:element name="txPr" type="CT_TextProps" minOccurs="0" maxOccurs="1"/>
<xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0" maxOccurs="1"/>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_StyleDefinition">
<xsd:sequence>
<xsd:element name="title" type="CT_SDName" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="desc" type="CT_SDDescription" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="catLst" type="CT_SDCategories" minOccurs="0"/>
<xsd:element name="scene3d" type="a:CT_Scene3D" minOccurs="0" maxOccurs="1"/>
<xsd:element name="styleLbl" type="CT_StyleLabel" minOccurs="1" maxOccurs="unbounded"/>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="uniqueId" type="xsd:string" use="optional" default=""/>
<xsd:attribute name="minVer" type="xsd:string" use="optional"/>
</xsd:complexType>
<xsd:element name="styleDef" type="CT_StyleDefinition"/>
<xsd:complexType name="CT_StyleDefinitionHeader">
<xsd:sequence>
<xsd:element name="title" type="CT_SDName" minOccurs="1" maxOccurs="unbounded"/>
<xsd:element name="desc" type="CT_SDDescription" minOccurs="1" maxOccurs="unbounded"/>
<xsd:element name="catLst" type="CT_SDCategories" minOccurs="0"/>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="uniqueId" type="xsd:string" use="required"/>
<xsd:attribute name="minVer" type="xsd:string" use="optional"/>
<xsd:attribute name="resId" type="xsd:int" use="optional" default="0"/>
</xsd:complexType>
<xsd:element name="styleDefHdr" type="CT_StyleDefinitionHeader"/>
<xsd:complexType name="CT_StyleDefinitionHeaderLst">
<xsd:sequence>
<xsd:element name="styleDefHdr" type="CT_StyleDefinitionHeader" minOccurs="0"
maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="styleDefHdrLst" type="CT_StyleDefinitionHeaderLst"/>
<xsd:simpleType name="ST_AlgorithmType" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="composite"/>
<xsd:enumeration value="conn"/>
<xsd:enumeration value="cycle"/>
<xsd:enumeration value="hierChild"/>
<xsd:enumeration value="hierRoot"/>
<xsd:enumeration value="pyra"/>
<xsd:enumeration value="lin"/>
<xsd:enumeration value="sp"/>
<xsd:enumeration value="tx"/>
<xsd:enumeration value="snake"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_AxisType" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="self"/>
<xsd:enumeration value="ch"/>
<xsd:enumeration value="des"/>
<xsd:enumeration value="desOrSelf"/>
<xsd:enumeration value="par"/>
<xsd:enumeration value="ancst"/>
<xsd:enumeration value="ancstOrSelf"/>
<xsd:enumeration value="followSib"/>
<xsd:enumeration value="precedSib"/>
<xsd:enumeration value="follow"/>
<xsd:enumeration value="preced"/>
<xsd:enumeration value="root"/>
<xsd:enumeration value="none"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_AxisTypes">
<xsd:list itemType="ST_AxisType"/>
</xsd:simpleType>
<xsd:simpleType name="ST_BoolOperator" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="none"/>
<xsd:enumeration value="equ"/>
<xsd:enumeration value="gte"/>
<xsd:enumeration value="lte"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_ChildOrderType" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="b"/>
<xsd:enumeration value="t"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_ConstraintType" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="none"/>
<xsd:enumeration value="alignOff"/>
<xsd:enumeration value="begMarg"/>
<xsd:enumeration value="bendDist"/>
<xsd:enumeration value="begPad"/>
<xsd:enumeration value="b"/>
<xsd:enumeration value="bMarg"/>
<xsd:enumeration value="bOff"/>
<xsd:enumeration value="ctrX"/>
<xsd:enumeration value="ctrXOff"/>
<xsd:enumeration value="ctrY"/>
<xsd:enumeration value="ctrYOff"/>
<xsd:enumeration value="connDist"/>
<xsd:enumeration value="diam"/>
<xsd:enumeration value="endMarg"/>
<xsd:enumeration value="endPad"/>
<xsd:enumeration value="h"/>
<xsd:enumeration value="hArH"/>
<xsd:enumeration value="hOff"/>
<xsd:enumeration value="l"/>
<xsd:enumeration value="lMarg"/>
<xsd:enumeration value="lOff"/>
<xsd:enumeration value="r"/>
<xsd:enumeration value="rMarg"/>
<xsd:enumeration value="rOff"/>
<xsd:enumeration value="primFontSz"/>
<xsd:enumeration value="pyraAcctRatio"/>
<xsd:enumeration value="secFontSz"/>
<xsd:enumeration value="sibSp"/>
<xsd:enumeration value="secSibSp"/>
<xsd:enumeration value="sp"/>
<xsd:enumeration value="stemThick"/>
<xsd:enumeration value="t"/>
<xsd:enumeration value="tMarg"/>
<xsd:enumeration value="tOff"/>
<xsd:enumeration value="userA"/>
<xsd:enumeration value="userB"/>
<xsd:enumeration value="userC"/>
<xsd:enumeration value="userD"/>
<xsd:enumeration value="userE"/>
<xsd:enumeration value="userF"/>
<xsd:enumeration value="userG"/>
<xsd:enumeration value="userH"/>
<xsd:enumeration value="userI"/>
<xsd:enumeration value="userJ"/>
<xsd:enumeration value="userK"/>
<xsd:enumeration value="userL"/>
<xsd:enumeration value="userM"/>
<xsd:enumeration value="userN"/>
<xsd:enumeration value="userO"/>
<xsd:enumeration value="userP"/>
<xsd:enumeration value="userQ"/>
<xsd:enumeration value="userR"/>
<xsd:enumeration value="userS"/>
<xsd:enumeration value="userT"/>
<xsd:enumeration value="userU"/>
<xsd:enumeration value="userV"/>
<xsd:enumeration value="userW"/>
<xsd:enumeration value="userX"/>
<xsd:enumeration value="userY"/>
<xsd:enumeration value="userZ"/>
<xsd:enumeration value="w"/>
<xsd:enumeration value="wArH"/>
<xsd:enumeration value="wOff"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_ConstraintRelationship" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="self"/>
<xsd:enumeration value="ch"/>
<xsd:enumeration value="des"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_ElementType" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="all"/>
<xsd:enumeration value="doc"/>
<xsd:enumeration value="node"/>
<xsd:enumeration value="norm"/>
<xsd:enumeration value="nonNorm"/>
<xsd:enumeration value="asst"/>
<xsd:enumeration value="nonAsst"/>
<xsd:enumeration value="parTrans"/>
<xsd:enumeration value="pres"/>
<xsd:enumeration value="sibTrans"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_ElementTypes">
<xsd:list itemType="ST_ElementType"/>
</xsd:simpleType>
<xsd:simpleType name="ST_ParameterId" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="horzAlign"/>
<xsd:enumeration value="vertAlign"/>
<xsd:enumeration value="chDir"/>
<xsd:enumeration value="chAlign"/>
<xsd:enumeration value="secChAlign"/>
<xsd:enumeration value="linDir"/>
<xsd:enumeration value="secLinDir"/>
<xsd:enumeration value="stElem"/>
<xsd:enumeration value="bendPt"/>
<xsd:enumeration value="connRout"/>
<xsd:enumeration value="begSty"/>
<xsd:enumeration value="endSty"/>
<xsd:enumeration value="dim"/>
<xsd:enumeration value="rotPath"/>
<xsd:enumeration value="ctrShpMap"/>
<xsd:enumeration value="nodeHorzAlign"/>
<xsd:enumeration value="nodeVertAlign"/>
<xsd:enumeration value="fallback"/>
<xsd:enumeration value="txDir"/>
<xsd:enumeration value="pyraAcctPos"/>
<xsd:enumeration value="pyraAcctTxMar"/>
<xsd:enumeration value="txBlDir"/>
<xsd:enumeration value="txAnchorHorz"/>
<xsd:enumeration value="txAnchorVert"/>
<xsd:enumeration value="txAnchorHorzCh"/>
<xsd:enumeration value="txAnchorVertCh"/>
<xsd:enumeration value="parTxLTRAlign"/>
<xsd:enumeration value="parTxRTLAlign"/>
<xsd:enumeration value="shpTxLTRAlignCh"/>
<xsd:enumeration value="shpTxRTLAlignCh"/>
<xsd:enumeration value="autoTxRot"/>
<xsd:enumeration value="grDir"/>
<xsd:enumeration value="flowDir"/>
<xsd:enumeration value="contDir"/>
<xsd:enumeration value="bkpt"/>
<xsd:enumeration value="off"/>
<xsd:enumeration value="hierAlign"/>
<xsd:enumeration value="bkPtFixedVal"/>
<xsd:enumeration value="stBulletLvl"/>
<xsd:enumeration value="stAng"/>
<xsd:enumeration value="spanAng"/>
<xsd:enumeration value="ar"/>
<xsd:enumeration value="lnSpPar"/>
<xsd:enumeration value="lnSpAfParP"/>
<xsd:enumeration value="lnSpCh"/>
<xsd:enumeration value="lnSpAfChP"/>
<xsd:enumeration value="rtShortDist"/>
<xsd:enumeration value="alignTx"/>
<xsd:enumeration value="pyraLvlNode"/>
<xsd:enumeration value="pyraAcctBkgdNode"/>
<xsd:enumeration value="pyraAcctTxNode"/>
<xsd:enumeration value="srcNode"/>
<xsd:enumeration value="dstNode"/>
<xsd:enumeration value="begPts"/>
<xsd:enumeration value="endPts"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_Ints">
<xsd:list itemType="xsd:int"/>
</xsd:simpleType>
<xsd:simpleType name="ST_UnsignedInts">
<xsd:list itemType="xsd:unsignedInt"/>
</xsd:simpleType>
<xsd:simpleType name="ST_Booleans">
<xsd:list itemType="xsd:boolean"/>
</xsd:simpleType>
<xsd:simpleType name="ST_FunctionType" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="cnt"/>
<xsd:enumeration value="pos"/>
<xsd:enumeration value="revPos"/>
<xsd:enumeration value="posEven"/>
<xsd:enumeration value="posOdd"/>
<xsd:enumeration value="var"/>
<xsd:enumeration value="depth"/>
<xsd:enumeration value="maxDepth"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_FunctionOperator" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="equ"/>
<xsd:enumeration value="neq"/>
<xsd:enumeration value="gt"/>
<xsd:enumeration value="lt"/>
<xsd:enumeration value="gte"/>
<xsd:enumeration value="lte"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_DiagramHorizontalAlignment" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="l"/>
<xsd:enumeration value="ctr"/>
<xsd:enumeration value="r"/>
<xsd:enumeration value="none"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_VerticalAlignment" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="t"/>
<xsd:enumeration value="mid"/>
<xsd:enumeration value="b"/>
<xsd:enumeration value="none"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_ChildDirection" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="horz"/>
<xsd:enumeration value="vert"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_ChildAlignment" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="t"/>
<xsd:enumeration value="b"/>
<xsd:enumeration value="l"/>
<xsd:enumeration value="r"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_SecondaryChildAlignment" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="none"/>
<xsd:enumeration value="t"/>
<xsd:enumeration value="b"/>
<xsd:enumeration value="l"/>
<xsd:enumeration value="r"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_LinearDirection" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="fromL"/>
<xsd:enumeration value="fromR"/>
<xsd:enumeration value="fromT"/>
<xsd:enumeration value="fromB"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_SecondaryLinearDirection" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="none"/>
<xsd:enumeration value="fromL"/>
<xsd:enumeration value="fromR"/>
<xsd:enumeration value="fromT"/>
<xsd:enumeration value="fromB"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_StartingElement" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="node"/>
<xsd:enumeration value="trans"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_RotationPath" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="none"/>
<xsd:enumeration value="alongPath"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_CenterShapeMapping" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="none"/>
<xsd:enumeration value="fNode"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_BendPoint" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="beg"/>
<xsd:enumeration value="def"/>
<xsd:enumeration value="end"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_ConnectorRouting" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="stra"/>
<xsd:enumeration value="bend"/>
<xsd:enumeration value="curve"/>
<xsd:enumeration value="longCurve"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_ArrowheadStyle" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="auto"/>
<xsd:enumeration value="arr"/>
<xsd:enumeration value="noArr"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_ConnectorDimension" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="1D"/>
<xsd:enumeration value="2D"/>
<xsd:enumeration value="cust"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_ConnectorPoint" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="auto"/>
<xsd:enumeration value="bCtr"/>
<xsd:enumeration value="ctr"/>
<xsd:enumeration value="midL"/>
<xsd:enumeration value="midR"/>
<xsd:enumeration value="tCtr"/>
<xsd:enumeration value="bL"/>
<xsd:enumeration value="bR"/>
<xsd:enumeration value="tL"/>
<xsd:enumeration value="tR"/>
<xsd:enumeration value="radial"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_NodeHorizontalAlignment" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="l"/>
<xsd:enumeration value="ctr"/>
<xsd:enumeration value="r"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_NodeVerticalAlignment" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="t"/>
<xsd:enumeration value="mid"/>
<xsd:enumeration value="b"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_FallbackDimension" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="1D"/>
<xsd:enumeration value="2D"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_TextDirection" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="fromT"/>
<xsd:enumeration value="fromB"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_PyramidAccentPosition" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="bef"/>
<xsd:enumeration value="aft"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_PyramidAccentTextMargin" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="step"/>
<xsd:enumeration value="stack"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_TextBlockDirection" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="horz"/>
<xsd:enumeration value="vert"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_TextAnchorHorizontal" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="none"/>
<xsd:enumeration value="ctr"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_TextAnchorVertical" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="t"/>
<xsd:enumeration value="mid"/>
<xsd:enumeration value="b"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_DiagramTextAlignment" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="l"/>
<xsd:enumeration value="ctr"/>
<xsd:enumeration value="r"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_AutoTextRotation" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="none"/>
<xsd:enumeration value="upr"/>
<xsd:enumeration value="grav"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_GrowDirection" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="tL"/>
<xsd:enumeration value="tR"/>
<xsd:enumeration value="bL"/>
<xsd:enumeration value="bR"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_FlowDirection" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="row"/>
<xsd:enumeration value="col"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_ContinueDirection" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="revDir"/>
<xsd:enumeration value="sameDir"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_Breakpoint" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="endCnv"/>
<xsd:enumeration value="bal"/>
<xsd:enumeration value="fixed"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_Offset" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="ctr"/>
<xsd:enumeration value="off"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_HierarchyAlignment" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="tL"/>
<xsd:enumeration value="tR"/>
<xsd:enumeration value="tCtrCh"/>
<xsd:enumeration value="tCtrDes"/>
<xsd:enumeration value="bL"/>
<xsd:enumeration value="bR"/>
<xsd:enumeration value="bCtrCh"/>
<xsd:enumeration value="bCtrDes"/>
<xsd:enumeration value="lT"/>
<xsd:enumeration value="lB"/>
<xsd:enumeration value="lCtrCh"/>
<xsd:enumeration value="lCtrDes"/>
<xsd:enumeration value="rT"/>
<xsd:enumeration value="rB"/>
<xsd:enumeration value="rCtrCh"/>
<xsd:enumeration value="rCtrDes"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_FunctionValue" final="restriction">
<xsd:union
memberTypes="xsd:int xsd:boolean ST_Direction ST_HierBranchStyle ST_AnimOneStr ST_AnimLvlStr ST_ResizeHandlesStr"
/>
</xsd:simpleType>
<xsd:simpleType name="ST_VariableType" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="none"/>
<xsd:enumeration value="orgChart"/>
<xsd:enumeration value="chMax"/>
<xsd:enumeration value="chPref"/>
<xsd:enumeration value="bulEnabled"/>
<xsd:enumeration value="dir"/>
<xsd:enumeration value="hierBranch"/>
<xsd:enumeration value="animOne"/>
<xsd:enumeration value="animLvl"/>
<xsd:enumeration value="resizeHandles"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_FunctionArgument" final="restriction">
<xsd:union memberTypes="ST_VariableType"/>
</xsd:simpleType>
<xsd:simpleType name="ST_OutputShapeType" final="restriction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="none"/>
<xsd:enumeration value="conn"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas"
xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
elementFormDefault="qualified"
targetNamespace="http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas">
<xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/main"
schemaLocation="dml-main.xsd"/>
<xsd:element name="lockedCanvas" type="a:CT_GvmlGroupShape"/>
</xsd:schema>
Related skills
Forks & variants (8)
Pptx has 8 known copies in the catalog totaling 1.4k installs. They canonicalize to this original listing.
- smithery.ai - 856 installs
- modelscope.cn - 221 installs
- jackiexiao - 147 installs
- skills.volces.com - 139 installs
- openakita - 24 installs
How it compares
Choose pptx when stakeholders need editable slides; use PDF or markdown exports when PowerPoint format is not required.
FAQ
What file format does pptx produce?
pptx produces editable Microsoft PowerPoint .pptx files that open in PowerPoint and other compatible presentation applications for further editing.
What input does pptx accept?
pptx accepts agent instructions or structured content and assembles slides into a standard .pptx deck without requiring manual PowerPoint authoring.
Is Pptx safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.