pptxboss.dev

PowerPoint to Markdown

PowerPoint to Markdown, three ways.

pptxboss turns a deck into a Markdown document: a heading per slide, bullets with their levels, GFM tables, images, chart tables and SmartArt outlines, with speaker notes and comments as block quotes on request. The same Rust engine answers from Python, from Rust and from the command line, and reads legacy .ppt decks through the same call.

Command line

One command, one file.

cargo install pptxboss-cli puts the pptxboss binary on your path. markdown writes to stdout and warns on stderr about anything skipped.

~/decks
$ pptxboss markdown deck.pptx > deck.md
$ pptxboss markdown --notes --comments deck.pptx     # block quotes after each slide
$ pptxboss markdown --slides 2-5 --no-images deck.pptx
$ pptxboss markdown legacy.ppt                       # PowerPoint 97-2003 too

Python

One method on the document.

pip install pptxboss installs prebuilt abi3 wheels for CPython 3.12 and later, no C toolchain involved. markdown() takes headings, notes, comments, hidden_slides, hidden_shapes, furniture, images and indexes.

convert.py
import pptxboss

doc = pptxboss.Document("deck.pptx")
markdown = doc.markdown(notes=True)        # whole deck
one_slide = doc[0].markdown()              # one slide, 0-based

Rust

One crate.

cargo add pptxboss-core is all it takes; Document::markdown renders the deck with the same options as the CLI and returns the Markdown with a report of anything skipped.

main.rs
use pptxboss_core::Document;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let doc = Document::open("deck.pptx")?;
    let (markdown, report) = doc.markdown(&Default::default());
    for warning in report.warnings() {
        eprintln!("warning: {warning}");
    }
    println!("{markdown}");
    Ok(())
}

What is preserved

What ends up in the file.

  • Slide order and titles: one ## heading per slide (or Slide N when a slide has no title), a rule between slides.
  • Bullets with their levels, numbered lists, and plain paragraphs for text without a bullet.
  • Tables as GFM pipe tables; merged-away cells are omitted.
  • Pictures as image references naming their image part; chart data as tables; SmartArt as an outline.
  • Speaker notes and comments, with authors, as block quotes when asked for.
9,868 files/s

Text extraction over 631 test-suite decks, chart and SmartArt text included.

0 C dependencies

Its own ZIP, DEFLATE and XML readers; abi3 wheels for CPython 3.12+.

Questions

How do I convert a PowerPoint deck to Markdown in Python?
pip install pptxboss, then pptxboss.Document("deck.pptx").markdown() returns the whole deck as Markdown. Each slide has the same method, and the CLI equivalent is pptxboss markdown deck.pptx.
What does the Markdown contain?
A ## heading per slide from its title, bullets with their indentation levels, plain paragraphs, GFM pipe tables for slide tables, image references for pictures, chart data as tables, SmartArt as nested outlines, and slides separated by a horizontal rule. Speaker notes and comments become block quotes when asked for.
Does it read charts and SmartArt?
Yes. Chart titles, series, categories and values are read as cached in the file and written as tables; SmartArt diagram text comes out as an outline. Nothing is recomputed from an embedded workbook.
Does it work on old .ppt files?
Yes. A PowerPoint 97-2003 deck opens through the same command and API and gives its text, titles, notes and pictures. Its tables, charts and comments are not read.
What about text formatting?
Bold, italic, underline, strikethrough, size, language, typeface and hyperlinks are read per run. Formatting inherited from a layout or master is not resolved, and text is never inherited, so an empty placeholder stays empty.