mirror of
https://github.com/PR0M3TH3AN/Artstr-Studio.git
synced 2026-11-04 20:50:39 +00:00
PPTX import P1.5: slide backgrounds (direct solid fills)
Quick win on top of Phase 1: pull each slide's direct background color out of p:bg/p:bgPr/a:solidFill/a:srgbClr and set it on the Artstr slide instead of always leaving the default white. Scoped narrowly: - Direct slide backgrounds only. p:bgRef (layout/master inheritance) emits LAYOUT_INHERITANCE_PARTIAL and stays white — Phase 6. - solidFill + srgbClr only. Gradient, picture, and scheme-color fills emit THEME_COLOR_UNRESOLVED and stay white — Phase 6. - Parse failures on a per-slide basis emit SLIDE_PARSE_FAILED and fall through to white; the deck shell still imports. Counts successful backgrounds in report.imported.backgrounds so the import report can show "16 backgrounds imported". readSlideBackground is exposed via _internals for future-phase tests. Verified end-to-end against the user's gallery_template_layout_set deck (16 slides, design-template set heavy on background colors): all 16 slides now import with their actual cream / themed colors (e.g. slide 1 = #fbf8f0) instead of plain white, with zero warnings. Synthetic-pptx smoke test (no p:bg) still produces white slides.
This commit is contained in:
1 parent
71e5370e36
commit
32af7f0e96
1 file changed
+76
-1
+76
-1
@@ -158,6 +158,58 @@ window.ArtstrPptxImporter = (function () {
|
||||
return refs;
|
||||
}
|
||||
|
||||
// ---- Slide-level parsing ---------------------------------------------
|
||||
// Read the slide's direct background. PPTX backgrounds can come from
|
||||
// four places (slide, layout, master, theme). This handler covers only
|
||||
// the direct slide background with a single solidFill — the common case
|
||||
// for design-template decks. Layout / master / theme inheritance and
|
||||
// gradient / picture fills are Phase 6.
|
||||
//
|
||||
// Returns either a CSS hex string like '#fbf8f0' or null if nothing
|
||||
// usable was found (caller leaves slide.background at the default).
|
||||
function readSlideBackground(slideDoc, slideIndex, report) {
|
||||
const bg = slideDoc.getElementsByTagName('p:bg')[0]
|
||||
|| slideDoc.getElementsByTagNameNS('*', 'bg')[0];
|
||||
if (!bg) return null;
|
||||
|
||||
// Direct background properties live in <p:bgPr>. <p:bgRef> means the
|
||||
// slide inherits from its layout/master via a theme scheme — defer
|
||||
// to Phase 6 with a warning.
|
||||
const bgRef = bg.getElementsByTagName('p:bgRef')[0]
|
||||
|| bg.getElementsByTagNameNS('*', 'bgRef')[0];
|
||||
if (bgRef) {
|
||||
_warn(report, slideIndex, 'LAYOUT_INHERITANCE_PARTIAL',
|
||||
`Slide ${slideIndex + 1}: background inherited from layout/master — not resolved in Phase 1.`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const bgPr = bg.getElementsByTagName('p:bgPr')[0]
|
||||
|| bg.getElementsByTagNameNS('*', 'bgPr')[0];
|
||||
if (!bgPr) return null;
|
||||
|
||||
// Only solidFill + srgbClr in Phase 1. gradFill, blipFill (picture),
|
||||
// pattFill, and schemeClr-based fills land in Phase 6 with the rest
|
||||
// of theme resolution.
|
||||
const solid = bgPr.getElementsByTagName('a:solidFill')[0]
|
||||
|| bgPr.getElementsByTagNameNS('*', 'solidFill')[0];
|
||||
if (!solid) {
|
||||
_warn(report, slideIndex, 'THEME_COLOR_UNRESOLVED',
|
||||
`Slide ${slideIndex + 1}: non-solid background fill (gradient / picture / scheme color) — left as default for now.`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const srgb = solid.getElementsByTagName('a:srgbClr')[0]
|
||||
|| solid.getElementsByTagNameNS('*', 'srgbClr')[0];
|
||||
if (!srgb) {
|
||||
_warn(report, slideIndex, 'THEME_COLOR_UNRESOLVED',
|
||||
`Slide ${slideIndex + 1}: background uses a scheme color — theme resolution is Phase 6.`);
|
||||
return null;
|
||||
}
|
||||
const hex = (srgb.getAttribute('val') || '').trim().toLowerCase();
|
||||
if (!/^[0-9a-f]{6}$/.test(hex)) return null;
|
||||
return '#' + hex;
|
||||
}
|
||||
|
||||
function readPresentationInfo(files, report) {
|
||||
const presText = readZipText(files, 'ppt/presentation.xml');
|
||||
if (!presText) {
|
||||
@@ -197,12 +249,34 @@ window.ArtstrPptxImporter = (function () {
|
||||
if (i && i % 10 === 0) {
|
||||
await new Promise((r) => requestAnimationFrame(r));
|
||||
}
|
||||
|
||||
// Try to read the slide's direct background. Anything we can't
|
||||
// resolve (inherited, gradient, scheme color) leaves the default
|
||||
// white — the user can edit it in the Deck Builder. Read failures
|
||||
// are non-fatal: the slide still gets a shell.
|
||||
let background = '#ffffff';
|
||||
const slidePath = presentation.slideRefs[i].path;
|
||||
const slideText = slidePath ? readZipText(files, slidePath) : null;
|
||||
if (slideText) {
|
||||
try {
|
||||
const slideDoc = parseXml(slideText);
|
||||
const bg = readSlideBackground(slideDoc, i, report);
|
||||
if (bg) {
|
||||
background = bg;
|
||||
report.imported.backgrounds += 1;
|
||||
}
|
||||
} catch (err) {
|
||||
_warn(report, i, 'SLIDE_PARSE_FAILED',
|
||||
`Slide ${i + 1}: could not parse slide XML — left blank.`);
|
||||
}
|
||||
}
|
||||
|
||||
slides.push({
|
||||
name: 'Slide ' + (i + 1),
|
||||
slide: {
|
||||
width: TARGET_W,
|
||||
height: TARGET_H,
|
||||
background: '#ffffff',
|
||||
background,
|
||||
notes: '',
|
||||
},
|
||||
layers: [],
|
||||
@@ -245,6 +319,7 @@ window.ArtstrPptxImporter = (function () {
|
||||
readSlideSize,
|
||||
readSlideRefsInOrder,
|
||||
readPresentationInfo,
|
||||
readSlideBackground,
|
||||
},
|
||||
};
|
||||
})();
|
||||
Reference in new issue
Block a user