mirror of
https://github.com/storytold/deckcraft.git
synced 2026-11-14 14:12:52 +00:00
Round-trip tables, charts, animation, media, sections and masters
An owned corpus of those deck kinds survives open, save and reopen. The check found the handout master — printed header, footer, date and slide number — was dropped on save, so import and export now keep that part.
This commit is contained in:
1 parent
457406a7a5
commit
034b312a64
8 files changed
+699
-24
No files matched your search
@@ -24,6 +24,7 @@ const CT_SLIDE: &str = "application/vnd.openxmlformats-officedocument.presentati
|
||||
const CT_LAYOUT: &str = "application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml";
|
||||
const CT_MASTER: &str = "application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml";
|
||||
const CT_NOTES_MASTER: &str = "application/vnd.openxmlformats-officedocument.presentationml.notesMaster+xml";
|
||||
const CT_HANDOUT_MASTER: &str = "application/vnd.openxmlformats-officedocument.presentationml.handoutMaster+xml";
|
||||
const CT_NOTES: &str = "application/vnd.openxmlformats-officedocument.presentationml.notesSlide+xml";
|
||||
const CT_THEME: &str = "application/vnd.openxmlformats-officedocument.theme+xml";
|
||||
const CT_PRES_PROPS: &str = "application/vnd.openxmlformats-officedocument.presentationml.presProps+xml";
|
||||
@@ -459,6 +460,29 @@ pub fn export(p: &Presentation) -> Result<Vec<u8>, PptxError> {
|
||||
notes_master_rid = Some(pres.rels.add("notesMaster", &opc::relative("ppt/presentation.xml", notes_master), false));
|
||||
}
|
||||
|
||||
// Handout master. Its header, footer, date and slide-number text live on this part; a deck
|
||||
// that has never had one does not gain an empty master on save.
|
||||
let handout_path = "ppt/handoutMasters/handoutMaster1.xml";
|
||||
let mut handout_rid = None;
|
||||
if let Some(hm) = p.handout_master.as_ref() {
|
||||
let tindex = p.masters.len() + 1 + usize::from(notes_master_rid.is_some());
|
||||
let tname = format!("ppt/theme/theme{tindex}.xml");
|
||||
let mut ho = Out::new(handout_path);
|
||||
ho.rels.add("theme", &opc::relative(handout_path, &tname), false);
|
||||
let mut to = Out::new(&tname);
|
||||
let txml = theme::theme_xml(&mut x, &mut to, &hm.theme);
|
||||
x.pkg.xml_part(&tname, CT_THEME, txml);
|
||||
x.pkg.rels(&tname, &to.rels);
|
||||
let mut w = W::new();
|
||||
root_open(&mut w, "p:handoutMaster", A::new());
|
||||
csld(&mut w, &mut x, &mut ho, &hm.name, hm.background.as_ref(), &hm.shapes);
|
||||
clr_map(&mut w, &hm.color_map);
|
||||
w.close("p:handoutMaster");
|
||||
x.pkg.xml_part(handout_path, CT_HANDOUT_MASTER, w.finish());
|
||||
x.pkg.rels(handout_path, &ho.rels);
|
||||
handout_rid = Some(pres.rels.add("handoutMaster", &opc::relative("ppt/presentation.xml", handout_path), false));
|
||||
}
|
||||
|
||||
// Comment authors.
|
||||
let mut authors: Vec<(String, String, u32)> = vec![];
|
||||
let mut n_comments = 0u32;
|
||||
@@ -514,7 +538,7 @@ pub fn export(p: &Presentation) -> Result<Vec<u8>, PptxError> {
|
||||
x.pkg.xml_part("ppt/viewProps.xml", CT_VIEW_PROPS, view_props_xml());
|
||||
let ts = crate::tables::table_styles_xml(&x.table_styles, &p.table_styles);
|
||||
x.pkg.xml_part("ppt/tableStyles.xml", CT_TABLE_STYLES, ts);
|
||||
let pxml = presentation_xml(&mut x, &mut pres, &master_rids, notes_master_rid.as_deref(), &slide_rids);
|
||||
let pxml = presentation_xml(&mut x, &mut pres, &master_rids, notes_master_rid.as_deref(), handout_rid.as_deref(), &slide_rids);
|
||||
x.pkg.xml_part("ppt/presentation.xml", CT_PRES, pxml);
|
||||
x.pkg.rels("ppt/presentation.xml", &pres.rels);
|
||||
|
||||
@@ -665,7 +689,7 @@ fn section_slides(p: &Presentation) -> Vec<(String, Vec<usize>)> {
|
||||
out
|
||||
}
|
||||
|
||||
fn presentation_xml(x: &mut Exp, o: &mut Out, masters: &[(u64, String)], notes: Option<&str>, slides: &[String]) -> Vec<u8> {
|
||||
fn presentation_xml(x: &mut Exp, o: &mut Out, masters: &[(u64, String)], notes: Option<&str>, handout: Option<&str>, slides: &[String]) -> Vec<u8> {
|
||||
let p = x.p;
|
||||
let mut w = W::new();
|
||||
let first = (p.first_slide_number != 1).then_some(p.first_slide_number.min(9999));
|
||||
@@ -680,6 +704,11 @@ fn presentation_xml(x: &mut Exp, o: &mut Out, masters: &[(u64, String)], notes:
|
||||
w.empty("p:notesMasterId", A::new().a("r:id", n));
|
||||
w.close("p:notesMasterIdLst");
|
||||
}
|
||||
if let Some(h) = handout {
|
||||
w.open0("p:handoutMasterIdLst");
|
||||
w.empty("p:handoutMasterId", A::new().a("r:id", h));
|
||||
w.close("p:handoutMasterIdLst");
|
||||
}
|
||||
if !slides.is_empty() {
|
||||
w.open0("p:sldIdLst");
|
||||
for (i, rid) in slides.iter().enumerate() {
|
||||
|
||||
Reference in new issue
Block a user