pptx-fix
v0.4.0
Published
Fix PowerPoint files that render incorrectly on macOS QuickLook and iOS. Built on quicklook-pptx-renderer for font metrics, text measurement, and issue detection. Resolves missing table borders, invisible shapes, flattened gradients, font reflow, and opaq
Maintainers
Readme
pptx-fix
Fix PowerPoint files that render incorrectly on macOS QuickLook and iOS. Rewrites PPTX internals so tables, shapes, gradients, and effects display correctly on Apple devices — no manual editing needed.
If your .pptx looks perfect in PowerPoint but looks wrong when someone opens it on a Mac or iPhone, this tool fixes it.
The Problem
Apple's QuickLook (macOS Finder spacebar preview), iOS Files app, and iPadOS use a private rendering engine called OfficeImport.framework — a completely independent OOXML parser that renders slides differently than Microsoft PowerPoint. Presentations created by python-pptx, PptxGenJS, Google Slides, Canva, LibreOffice, Pandoc, and other tools contain patterns that PowerPoint handles fine but OfficeImport renders incorrectly.
Common artifacts:
- Table borders vanish — generators set a table style reference, but OfficeImport only reads explicit border properties
- Shapes disappear — ~120 preset geometries (heart, cloud, lightningBolt, sun, moon...) are silently dropped
- Gradients become flat colors — 3+ color stops are averaged to a single solid color
- Drop shadows become opaque blocks — shapes with effects render as opaque PDF images that cover content behind them
- Fonts shift and text reflows — Calibri becomes Helvetica Neue, Arial becomes Helvetica, with different metrics
- Embedded fonts ignored — custom fonts embedded in the PPTX are completely ignored by QuickLook, falling back to system substitutes
pptx-fix rewrites the OOXML XML inside the PPTX ZIP to work around these OfficeImport quirks. The output is a valid .pptx that looks correct in both PowerPoint and Apple's preview.
Install
npm install pptx-fixUsage
CLI
# Fix a PPTX file
npx pptx-fix input.pptx -o output.pptx
# Apply only specific transforms
npx pptx-fix input.pptx -o output.pptx --only table-styles,gradients,fonts
# See what was changed
npx pptx-fix input.pptx -o output.pptx --report
# Analyze without fixing (dry run)
npx pptx-fix analyze input.pptxAs a Library
import { fix } from "pptx-fix";
import { readFileSync, writeFileSync } from "fs";
const input = readFileSync("presentation.pptx");
const result = await fix(input, { report: true });
writeFileSync("fixed.pptx", result.buffer);
console.log(result.report);Analyze Only
import { analyze } from "pptx-fix";
const issues = await analyze(pptxBuffer);
for (const issue of issues) {
console.log(`[${issue.severity}] Slide ${issue.slide}: ${issue.description}`);
}Transforms
| Transform | Status | What it fixes |
|-----------|--------|--------------|
| table-styles | Done | Resolves tableStyleId references and inlines explicit <a:lnL/R/T/B> borders on every cell. Handles firstRow, lastRow, bandRow conditional formatting. Only adds borders where none are explicitly defined. |
| geometries | Done | Replaces unsupported <a:prstGeom> presets (~120 shapes not in OfficeImport's supported set) with the visually-closest supported alternative (e.g. heart→ellipse, cloud→cloudCallout) so shapes are visible instead of invisible. |
| gradients | Done | Collapses 3+ stop gradients to 2-stop (first + last color) so QuickLook renders a gradient instead of a flat color. |
| effects | Done | Strips <effectLst> and <effectDag> (drop shadow, glow, reflection) from shape properties to prevent opaque PDF block rendering. |
| fonts | Done | Replaces high-risk Windows fonts (Calibri +14.4%, Segoe UI +14%, Corbel +18.8%, etc.) with metrically-closest Apple system font (from 29 fonts preinstalled on both macOS and iOS). Prefers narrower substitutes to avoid text overflow. Also fixes fonts in theme XML. |
| groups | Done | Ungroups shape groups so children render individually instead of being merged into a single opaque PDF block. Transforms child coordinates from group-space to slide-space. Skips rotated groups. |
| embedded-fonts | Done | Strips embedded font data (ignored by QuickLook) and replaces font references with the metrically-closest Apple system font. E.g. Montserrat → DIN Alternate (-4.3% width). Reduces file size and ensures consistent rendering. |
| text-fit | Done | Measures actual rendered text using canvas with macOS system fonts. Detects text that overflows its box or overlaps adjacent text after font replacement, and shrinks font sizes by the exact amount needed to fit. |
| chart-fallbacks | Done | Renders charts to PNG and embeds as fallback images so QuickLook displays charts instead of blank rectangles. Requires Playwright (optional — skips silently if not installed). |
All issue detection, font metrics, and text measurement are provided by quicklook-pptx-renderer. Run pptx-fix analyze to see all issues, or use the renderer's linter directly in CI.
Which Tools Produce Affected Files
| Tool | Primary issue on Mac/iPhone |
|------|---|
| python-pptx | Tables render without borders — the #1 reported issue. Style references not resolved by OfficeImport. |
| PptxGenJS | Missing thumbnails, shape rendering differences, effect artifacts |
| Google Slides export | Font substitution, formatting shifts, missing content types |
| Canva export | Fonts substituted, layout differences, animation artifacts |
| LibreOffice Impress | Table styles unresolved, gradient rendering differences |
| Pandoc / Quarto | Content type corruption, missing shapes, "PowerPoint found a problem with content" errors |
| Apache POI | Content type errors (InvalidFormatException: Package should contain a content type part [M1.13]) |
| Aspose.Slides | Missing thumbnail if refresh_thumbnail not called |
| Open XML SDK | Repair errors, missing relationships |
How It Works
Built on top of quicklook-pptx-renderer — an open-source rendering engine that replicates Apple's QuickLook PPTX output pixel for pixel. The renderer provides the font metrics database, macOS font substitution maps, text measurement via canvas, and a linter that detects every class of issue this tool fixes. It runs on Linux/Docker without a Mac.
PPTX (ZIP) → extract XML → parse → apply transforms → measure text → serialize → repack ZIP- Extract — JSZip opens the PPTX ZIP archive
- Parse — fast-xml-parser converts slide XML to objects, preserving all unknown elements
- Transform — each transform mutates the XML to work around OfficeImport quirks, using font metrics and substitution data from the renderer
- Measure — the text-fit transform measures actual rendered text with canvas using macOS system fonts, verifying that post-transform text still fits
- Serialize — XMLBuilder converts back to XML, JSZip produces a new valid PPTX
# Analyze issues without fixing (uses the renderer's linter)
npx pptx-fix analyze presentation.pptx
# Lint directly with the renderer (JSON output for CI)
npx quicklook-pptx lint presentation.pptx --json
# Render slides as PNG (see exactly what Mac users see)
npx quicklook-pptx render presentation.pptx --out ./slides/Dependencies
| Package | Purpose | |---------|---------| | quicklook-pptx-renderer | Font metrics, font substitution maps, text measurement, and issue detection — all transforms depend on its data | | @napi-rs/canvas | Canvas-based text measurement with macOS system fonts for text-fit transform | | jszip | ZIP extraction/repacking | | fast-xml-parser | OOXML XML parsing and serialization |
License
MIT
