Skip to content

fix(makeXmlContTypes): correct jpg MIME + drop ghost slideMaster Overrides (closes #1444)#1462

Open
IgnasStark wants to merge 1 commit into
gitbrent:masterfrom
IgnasStark:fix-makexmlconttypes-jpg-mime-and-ghost-masters
Open

fix(makeXmlContTypes): correct jpg MIME + drop ghost slideMaster Overrides (closes #1444)#1462
IgnasStark wants to merge 1 commit into
gitbrent:masterfrom
IgnasStark:fix-makexmlconttypes-jpg-mime-and-ghost-masters

Conversation

@IgnasStark
Copy link
Copy Markdown

Summary

Two long-standing bugs in [Content_Types].xml generation, both inside makeXmlContTypes() at src/gen-xml.ts. Both fixed in one PR because they share the same two-line region of the function and are mechanically tiny.

Bug 1 — image/jpg is not an IANA-registered MIME

-	strXml += '<Default Extension="jpg" ContentType="image/jpg"/>'
+	strXml += '<Default Extension="jpg" ContentType="image/jpeg"/>'

image/jpg does not exist in the IANA registry — the valid type is image/jpeg. PPT files generated with image/jpg open in lenient parsers (PowerPoint Desktop, Keynote, LibreOffice, Google Slides) but trigger strict-mode warnings in OOXML linters and some compliance-focused parsers (e.g. SoftMaker FreeOffice). The file extension on the binary stays .jpg; only the MIME changes.

Bug 2 — ghost slideMaster Overrides (closes #1444)

 strXml += '<Override PartName="/ppt/notesMasters/notesMaster1.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.notesMaster+xml"/>'
+strXml += '<Override PartName="/ppt/slideMasters/slideMaster1.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml"/>'
 slides.forEach((slide, idx) => {
-    strXml += `<Override PartName="/ppt/slideMasters/slideMaster${idx + 1}.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml"/>`
     strXml += `<Override PartName="/ppt/slides/slide${idx + 1}.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slide+xml"/>`

The slides.forEach loop currently emits one <Override PartName="/ppt/slideMasters/slideMaster${idx + 1}.xml"/> per slide, but PptxGenJS only ever serializes a single slideMaster1.xml to the zip (see genMasterSlide() which writes one master regardless of slide count). Result: an N-slide deck declares N slideMaster Overrides in [Content_Types].xml but only slideMaster1.xml exists on disk — N-1 ghost references.

PowerPoint Desktop tolerates this and silently ignores the ghosts. Stricter parsers report orphan Overrides; some online viewers (and PowerPoint Repair if the file is round-tripped) flag the file as corrupt and rewrite it.

The fix is structural: hoist a single literal slideMaster1.xml Override above the slides.forEach and drop the per-slide templated line. The forEach still iterates for slides/slide${idx+1}.xml Overrides and chart Overrides — only the slideMaster line is hoisted out.

Tracked at issue #1444 (open Feb 2026).

Verification

Generated a 2-slide deck with this branch applied, inspected [Content_Types].xml:

metric before after
slideMaster<N>.xml Override count for 2-slide deck 2 (ghost) 1
Extension="jpg" ContentType="image/jpg" 1 0
Extension="jpg" ContentType="image/jpeg" 0 1
slide<N>.xml Override count 2 2 (unchanged)
File opens in PowerPoint Desktop / Keynote / Slides / LibreOffice

No behaviour change for lenient parsers; strict-mode warnings cleared.

Context

Downstream consumer (Skaylink Presentation Generator) is shipping this exact patch via patch-package against pptxgenjs@4.0.1 because the upstream issue has been open since Feb 2026 without movement. Filing this PR as the courtesy upstream contribution so future versions don't need the patch.

…rides

Two long-standing bugs in [Content_Types].xml generation, both inside
makeXmlContTypes() at src/gen-xml.ts:

1. `image/jpg` is not an IANA-registered MIME — the valid type is
   `image/jpeg`. PPT files generated with `image/jpg` open in lenient
   parsers but trigger strict-mode warnings (e.g. SoftMaker FreeOffice,
   some OOXML linters). Extension stays `jpg` (the binary on disk is
   still .jpg); only the ContentType changes.

2. The slides.forEach loop emits one `<Override>` per slide pointing at
   `/ppt/slideMasters/slideMaster${idx+1}.xml`, but PptxGenJS only ever
   serializes slideMaster1.xml to the zip. Result: an N-slide deck has
   N-1 ghost slideMaster Overrides declared in [Content_Types].xml with
   no corresponding part on disk. Fix: hoist a single literal
   slideMaster1.xml Override above the loop; drop the per-slide
   templated line.

Closes gitbrent#1444.

The two changes are independent but share the same two-line area of the
function; combining them in one PR keeps the diff small and the review
focused.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Content_Types.xml references phantom slideMaster entries for multi-slide presentations

2 participants