fix(convert): strip auto <p:style> theme refs from PDF→PPTX shapes#43
Merged
Conversation
User reported that slide 1 of the converted UFCD 1492 deck rendered
correctly in PowerPoint (dark dotted background, blue UFCD 1492 badge,
title, etc.) but slide 6 looked blank — only the floating text was
visible, the dark navy header bar / blue separator / dark code block /
4 light-gray cards were all invisible. The PPTX inspect script
confirmed the slide's XML contained 13 valid <p:sp> elements with
correct <a:solidFill><a:srgbClr val="..."/></a:solidFill> for each
rectangle. So the file was fine; PowerPoint was deciding not to render
the rectangles on that specific slide.
Root cause: python-pptx's `slide.shapes.add_shape(...)` always emits
both <p:spPr> (with our explicit fill) AND <p:style> blocks like
<p:style>
<a:lnRef idx="1"><a:schemeClr val="accent1"/></a:lnRef>
<a:fillRef idx="3"><a:schemeClr val="accent1"/></a:fillRef>
<a:effectRef idx="2"><a:schemeClr val="accent1"/></a:effectRef>
<a:fontRef idx="minor"><a:schemeClr val="lt1"/></a:fontRef>
</p:style>
That style references the default theme's preset effects — `effectRef
idx="2"` is "moderate effect" which can apply gradients / soft edges /
opacity overlays. Per the OOXML spec, <p:spPr> should win over
<p:style>, but PowerPoint's renderer applies the theme effect *on top*
in some cases (apparently triggered by the specific shape mix on slide
6 — many overlapping rectangles plus 21 textboxes), masking the
explicit fill colour entirely. LibreOffice and python-pptx-based
inspection both ignore the style block and show the explicit fill,
which is why our diagnostics looked correct but PowerPoint rendered
blank.
Strip the auto-generated <p:style> element after add_shape() — every
drawing-extraction shape now emits with only <p:spPr>, so PowerPoint
has to use our explicit colour.
Verified on Linux Py3.14: a 1-page PDF with 3 filled rectangles (dark
navy header, blue separator, dark code block) now produces a PPTX with
4 shapes total (incl. white full-slide bg) and 0 <p:style> blocks.
Before this commit, every shape carried the theme reference.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
User reported that slide 1 of his UFCD 1492 deck rendered correctly in PowerPoint (dark dotted background, blue UFCD 1492 badge, title, etc.) but slide 6 looked blank — only the floating text was visible. The PPTX inspect script we wrote confirmed the slide's XML contained 13 valid
<p:sp>elements with correct<a:solidFill><a:srgbClr val="..."/></a:solidFill>for each rectangle. So the file was fine; PowerPoint was deciding not to render those specific rectangles.The user's slide 6 XML showed each shape carrying both:
Root cause
python-pptx'sslide.shapes.add_shape(...)always emits an auto<p:style>block with theme presets (effectRef "moderate effect 2", fillRef "intense fill 3"). Per the OOXML spec,<p:spPr>should win over<p:style>, but PowerPoint's renderer applies the theme effect on top in some shape-mix configurations (apparently triggered on slide 6 by the combination of overlapping rectangles + 21 textboxes), masking the explicit colour entirely. LibreOffice and python-pptx-based inspection both correctly use the explicit fill, which is why our diagnostics looked clean while PowerPoint silently rendered blank.Fix
Strip the auto-generated
<p:style>element afteradd_shape()returns. Every drawing-extraction shape now emits only<p:spPr>so PowerPoint has to use the explicit colour we set:Test plan
<p:style>blocks. Before this commit every shape carried the theme reference.🤖 Generated with Claude Code