HTML to PPT: Keep text and tables editable

Convert HTML to PPT with a structural reader when the source already contains headings and table cells. Separate semantic articles, CSS grids, and script-generated content before choosing a converter: they need different preparation. The local exports in this guide contain native PowerPoint text and table objects where the source supplies that structure. They are PPTX files. Browser styling and slide layout remain separate work.

Classify the source before choosing an HTML to PPT route

Choose the route from the downloaded HTML, because a browser can display content that a static converter never receives.

Open the saved source in a text editor and search for a distinctive table heading or sentence. Its location determines whether the next step is conversion, restructuring, or retrieving the rendered content.

What the page contains How to identify it in the source Route
A semantic article with a data table Headings and values appear inside heading tags and <table> cells Use Pandoc directly, or review extracted Markdown before export
A grid arranged with CSS Values appear inside <div> elements, with grid or flex layout rules Rebuild a semantic table before using a structural converter
Content inserted by JavaScript The target container is empty. The values appear only in script code or a later request Obtain the populated content before converting it

A website may combine them: the article can be static while its comparison table loads after the page opens. Search inside the table itself before treating the entire page as a static document. 17

Pandoc preserves semantic tables as native objects

Use Pandoc directly for a semantic article when your goal is editable content rather than a copy of the webpage's layout.

Pandoc reads HTML into a document structure, then writes that structure to PowerPoint. Its HTML reader recognizes a table as a table node. The PPTX writer maps that node to a native table. Our semantic article produced a PowerPoint table object containing the source headers and data cells. The exported text was also stored in text shapes, without a screenshot of the page. 1237

pandoc input.html --from=html --to=pptx --slide-level=2 \
          --metadata=title: --output output.pptx
        

The slide level makes section headings start slides. Clear the document title metadata when the article's own main heading already supplies the title: our default HTML export repeated it because the page also supplied an HTML <title>. The command above removed that extra title slide while retaining the table. Text before the first section heading can still occupy a slide without a title. 127

Output from our semantic article sample, unedited:

# Debugging Slow Database Migrations
        
        A migration that runs in seconds on a laptop can hold locks for minutes in production. The difference usually comes from table size and from other sessions waiting behind the migration.
        

Our source placed the article inside <main>, and Pandoc omitted the surrounding navigation, cookie notice, and footer. Removing only that wrapper caused the surrounding text to enter the export. The HTML reader's main-content selection explains the difference. It is not evidence that Pandoc can identify every article on an arbitrary website. 27

Failure condition What you will see Preparation
Site furniture sits outside an article without a main wrapper Menu and footer text appear alongside the article Keep only the intended article container
The page has both title metadata and a matching main heading Repeated title slides in the default export Clear the redundant document title metadata
A table exists only as a CSS layout Cell words survive as text, with no native table Restore rows and cells before export

Markdown exposes clutter before it becomes slide content

Add Markdown as an inspection step when you need to edit the extracted article before building slides.

MarkItDown can expose headings, paragraphs, code, and table rows for that review. In our HTML test it retained the semantic table, but it also retained the website wrapper. Its HTML converter selects the body after removing script and style elements. It does not select the article's main container. 47

from pathlib import Path
        from markitdown import MarkItDown
        from markitdown.converters import HtmlConverter
        
        converter = MarkItDown(enable_builtins=False, enable_plugins=False)
        converter.register_converter(HtmlConverter())
        result = converter.convert_local("input.html")
        Path("output.md").write_text(result.text_content, encoding="utf-8")
        

Output from our article-with-navigation sample, unedited:

We use cookies to improve your experience.
        
        Engineering notes from the infrastructure team
        

Delete the surrounding site text in the Markdown before exporting the deck. Leaving it untouched carried the same clutter into the generated PowerPoint. 7

pandoc output.md --from=gfm --to=pptx --slide-level=2 --output output.pptx
        

Exporting the unedited intermediate produced a native PowerPoint table. The CSS-grid variant lost its row structure before this step, so the same export command could not turn the loose words back into cells. For content you intend to rearrange substantially, fix the headings and table structure in Markdown, then export. For an already clean semantic article, the direct route avoids that extra handoff. 7

Markovo prepares content before the PPTX step

Use Markovo at the content-extraction stage of an existing API workflow, then send its Markdown to a separate PPTX writer.

Our stored HTML conversion returned the article without its navigation and footer, and kept its semantic table. It retained the same article and table content as the direct Pandoc extraction, while omitting the wrapper text retained by the MarkItDown path. A local Pandoc export of the stored Markdown also contained a native table. This service result covers the shared static article, not the derived CSS or JavaScript variants. 7910

Output from our stored semantic article sample, unedited:

## Find the Locking Statement
        
        Start with the sessions that are active while the migration waits. The wait event column shows whether a session is blocked on a lock or on input and output.
        

Table text from the direct Pandoc export, its title-cleared variant, and both Markdown-to-PPTX paths, unedited:

| Batch size | Rows per second | Lock wait (ms) |
        | --- | --- | --- |
        | 1000 | 8200 | 3 |
        | 10000 | 9100 | 41 |
        | 100000 | 9300 | 620 |
        

The stored result comes from an authenticated HTML upload, job polling, and a Markdown download. The separate API and CLI examples were not executed for this guide against the service. The API example used a fake HTTP transport. 911121415

The service produces Markdown, not a PowerPoint deck. Export the downloaded Markdown with the earlier Pandoc command. A timeout after upload calls for polling the known job, not repeating the compatibility upload: a repeated request can create another job. 1112

Boundary Observed result or limit
Shared semantic article Article, code and table retained without the website wrapper
CSS-grid and script variants Not executed for this guide through the service
Need to reproduce webpage coordinates and styling The measured output is Markdown, not a rendered webpage or finished deck

For a public HTTPS source, URL to Markdown is a separate authenticated beta import route. It fetches authorized public content without your browser session. Browser-only and login-only pages fall outside that route. The local HTML upload tested here does not establish results for that URL importer. 1113

CSS grids and scripts need a different input

Restore semantic content before exporting when the source has layout cells or script code instead of a populated HTML table.

Our CSS-grid variant kept the original cell words, but both local extraction paths separated them into text blocks. Neither resulting deck contained a native table. The source had no table node for the PowerPoint writer to preserve. 37

Output from our CSS-grid sample, unedited:

Batch size
        
        Rows per second
        
        Lock wait (ms)
        

The script variant failed earlier: the table values never reached the visible document content parsed by either local path. The source contained a script that would populate an empty container in a browser. A static parser did not run it. Changing only the PPTX output settings cannot recover those missing values. 247

Symptom Distinguishing check Action
Words remain, but the table became loose text Values are in layout divs rather than table cells Rebuild the row and cell structure
The table is absent altogether Values occur only in scripts, or the downloaded container is empty Retrieve populated HTML or export the table data from its source
The content is present but the page's visual arrangement is lost The requirement is CSS geometry rather than document structure Evaluate a browser-based DOM conversion path separately

GX-Alex/html2pptx describes a browser-based DOM-to-PowerPoint route. It was not executed for this guide. Its documented approach is relevant to CSS geometry, but the tests here do not establish its handling of this corpus. 6

Keep the source table semantic, remove page furniture, and generate the deck from that cleaned structure. If the table exists only after script execution, obtaining it comes before choosing the slide writer.

How we tested

The experiment checked source-content retention and native PPTX structure, not browser rendering, slide appearance, or editing in Microsoft PowerPoint.

Markovo is the service we build. It ran through the same corpus and scorer as the other paths; its row is reported in full, including where it scored lower.

Its API result covers only the shared article.html baseline. The derived CSS, script, and no-main samples were not executed through Markovo for this guide. The API snapshot records a successful run created on 2026-10-14. All local conversions, PPTX inspection, and rescoring were performed on 2026-11-04. Its recorded pages_total=1 and pages_ocr=0 describe this HTML run, not an OCR benchmark. Its applicable extraction scores matched Pandoc's baseline, so there are no lower-scoring cells to report. API timing is unavailable. The supplied zero placeholder was discarded. 79

Corpus and boundaries

File Representation
article.html Supplied semantic article inside main, with navigation, cookie notice, footer, code and a data table
article-no-main.html Same article with only the main wrapper removed
article-css-grid.html Same table words in div cells arranged by CSS Grid
article-script-table.html Original table assigned into an empty div by JavaScript

Every sample has a same-named .truth.json derived from the supplied baseline. The expected script-table content is the content after execution. Static omission therefore counts as a missing table. The database throughput numbers are synthetic fixture values, not converter performance measurements. No PDF, scan, OCR, formula, or browser-renderer benchmark was performed. 8

Tools, options and commands

Python 3.11.14, Pandoc 3.11, MarkItDown 0.1.8 with only HtmlConverter registered and with built-ins and plugins disabled, BeautifulSoup 4.15.0, markdownify 1.2.3, python-pptx 1.0.2, and lxml 6.1.3. The stored Markovo response identifies rate-card version 2026-09-19.v3-media-unified, not a converter package version. The stored CLI example was checked against the supplied install contract, not executed for this guide. The stored API example used a fake HTTP transport for multipart submission, running-to-succeeded polling and download. It was not executed for this guide against the service. 1415 891112

PYTHONDONTWRITEBYTECODE=1 tools/lab-venv/bin/python runs/2026-11-04-markovo-html-to-ppt/lab/run_html_to_ppt.py
        tools/lab-venv/bin/python tools/lab_score.py --lab runs/2026-11-04-markovo-html-to-ppt/lab --out runs/2026-11-04-markovo-html-to-ppt/lab/scores.json --markdown runs/2026-11-04-markovo-html-to-ppt/lab/scores.md
        PYTHONDONTWRITEBYTECODE=1 tools/lab-venv/bin/python runs/2026-11-04-markovo-html-to-ppt/lab/run_html_to_ppt.py --attach-structures
        

Pandoc's extraction options were --from=html --to=gfm --wrap=none. Direct decks used --from=html --to=pptx --slide-level=2. Markdown decks used --from=gfm --to=pptx --slide-level=2. The title-removal check added --metadata=title: on the baseline only. Full subprocess arguments are in lab/commands.json. The runner derives the variants from the baseline, without network access. 8

Scoring and raw evidence

The unchanged tools/lab_score.py, copied as lab/scorer.py, measures normalized sentence recall, adjacent paragraph-anchor order, same-line table row/header retention, Markdown pipe-table detection, heading text/level, fenced code and specified boilerplate exclusion. It does not measure visual similarity or PPTX editability. Timings are single calls for different stages, not comparable speed estimates. 5

Extraction outputs, directly summarized from lab/scores.json:

Tool Sample Prose Order Rows Header Pipe Headings Levels Code Clutter excluded Seconds
pandoc-html article 1.0 1.0 1.0 1.0 true 1.0 1.0 1.0 1.0 0.03031
markitdown-html article 1.0 1.0 1.0 1.0 true 1.0 1.0 1.0 0.0 0.004974
pandoc-html article-no-main 1.0 1.0 1.0 1.0 true 1.0 1.0 1.0 0.0 0.0295
markitdown-html article-no-main 1.0 1.0 1.0 1.0 true 1.0 1.0 1.0 0.0 0.004321
pandoc-html article-css-grid 1.0 1.0 0.0 0.0 false 1.0 1.0 1.0 1.0 0.084905
markitdown-html article-css-grid 1.0 1.0 0.0 0.0 false 1.0 1.0 1.0 0.0 0.004702
pandoc-html article-script-table 1.0 1.0 0.0 0.0 false 1.0 1.0 1.0 1.0 0.083453
markitdown-html article-script-table 1.0 1.0 0.0 0.0 false 1.0 1.0 1.0 0.0 0.007004
markovo article 1.0 1.0 1.0 1.0 true 1.0 1.0 1.0 1.0 n/a

PPTX inspection transcripts, scored with the same definitions:

Tool Sample Prose Order Rows Header Pipe Headings Levels Code Clutter excluded Seconds
pandoc-pptx article 1.0 1.0 1.0 1.0 true 1.0 0.3333 0.0 1.0 0.117628
markitdown-pandoc-pptx article 1.0 1.0 1.0 1.0 true 1.0 0.3333 0.0 0.0 0.052666
pandoc-pptx article-no-main 1.0 1.0 1.0 1.0 true 1.0 0.3333 0.0 0.0 0.108318
markitdown-pandoc-pptx article-no-main 1.0 1.0 1.0 1.0 true 1.0 0.3333 0.0 0.0 0.104009
pandoc-pptx article-css-grid 1.0 1.0 0.0 0.0 false 1.0 0.3333 0.0 1.0 0.05282
markitdown-pandoc-pptx article-css-grid 1.0 1.0 0.0 0.0 false 1.0 0.3333 0.0 0.0 0.119265
pandoc-pptx article-script-table 1.0 1.0 0.0 0.0 false 1.0 0.3333 0.0 1.0 0.115801
markitdown-pandoc-pptx article-script-table 1.0 1.0 0.0 0.0 false 1.0 0.3333 0.0 0.0 0.133955
pandoc-pptx-no-title article 1.0 1.0 1.0 1.0 true 1.0 0.3333 0.0 1.0 0.055075
markovo-pandoc-pptx article 1.0 1.0 1.0 1.0 true 1.0 0.3333 0.0 1.0 0.067849

The PPTX rows score a serialized inspection transcript. Its headings are all emitted with a single hash, and code text is not fenced, so its heading-level and code-fence scores reflect the transcript format. They do not show that PowerPoint lost the original code text. The object inspection separately counts native tables using python-pptx and cross-checks them against a:tbl elements in slide XML. Those mechanically generated counts are attached under pptx_structures in lab/scores.json. The scorer's original cells remain unchanged. 578

Tool Sample Slides Native tables Text shapes Picture shapes
pandoc-pptx article 5 1 7 0
markitdown-pandoc-pptx article 5 1 8 0
pandoc-pptx article-no-main 6 1 9 0
markitdown-pandoc-pptx article-no-main 5 1 8 0
pandoc-pptx article-css-grid 5 0 7 0
markitdown-pandoc-pptx article-css-grid 5 0 7 0
pandoc-pptx article-script-table 5 0 7 0
markitdown-pandoc-pptx article-script-table 5 0 7 0
pandoc-pptx-no-title article 4 1 6 0
markovo-pandoc-pptx article 4 1 6 0

Raw extraction files are lab/pandoc-html/<sample>.md, lab/markitdown-html/<sample>.md, and lab/markovo/article.md. PPTX transcripts and raw slide XML text are under lab/pandoc-pptx/, lab/markitdown-pandoc-pptx/, lab/pandoc-pptx-no-title/, and lab/markovo-pandoc-pptx/. The inspected .pptx and input .html files stay local. The publishable baseline source is lab/corpus/article-source.txt. Copy it to lab/corpus/article.html before running the script. Ground truths, the runner, stored API response and score tables accompany the evidence. 78910

Sources

  1. Pandoc 3.11 manual
  2. Pandoc 3.11 HTML reader: readHtml, extractMain, pHead
  3. Pandoc 3.11 PowerPoint writer: blockToShape
  4. MarkItDown 0.1.8 HtmlConverter source
  5. Unchanged copy of tools/lab_score.py
  6. GX-Alex/html2pptx README: not executed
  7. Measured scores and mechanically attached native PPTX structures
  8. Local experiment runner and object inspector
  9. Stored Markovo API response: created 2026-10-14
  10. Stored Markovo Markdown output for the shared article
  11. Supplied Markovo developer.md snapshot
  12. Supplied Markovo install.md snapshot
  13. Supplied Markovo keyword and capability ownership snapshot
  14. Executed snippet and fake-transport checks
  15. Local snippet-check runner, with no real API call