mirror of
https://github.com/storytold/deckcraft.git
synced 2026-10-27 03:56:50 -06:00
Merge PR #212 from justinjohn0306: PPTX: .potx and .ppsx declare a template and slide show main part (#210)
# Conflicts: # crates/pptx/tests/roundtrip.rs
This commit is contained in:
@@ -129,10 +129,10 @@ fn open_bytes(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
Ok(json!({"document": i, "missingFonts": s.doc()?.missing_fonts}))
|
||||
}
|
||||
|
||||
/// Encode the presentation in `format` (`deckcraft`, `pptx`, `outline`).
|
||||
/// Encode the presentation in `format` (`deckcraft`, `pptx`, `potx`, `ppsx`, `outline`, `pdf`).
|
||||
pub fn save_bytes(doc: &Presentation, format: &str) -> Result<Vec<u8>> {
|
||||
match format {
|
||||
"pptx" | "potx" | "ppsx" => deckcraft_pptx::export(doc).map_err(|e| EngineError::Other(e.to_string())),
|
||||
f @ ("pptx" | "potx" | "ppsx") => deckcraft_pptx::export_as(doc, f).map_err(|e| EngineError::Other(e.to_string())),
|
||||
"outline" | "txt" => Ok(deckcraft_format::slides_to_outline(doc).into_bytes()),
|
||||
"pdf" => deckcraft_pdf::export(doc, &Default::default()).map_err(|e| EngineError::Other(e.to_string())),
|
||||
_ => deckcraft_format::save(doc).map_err(|e| EngineError::Other(e.to_string())),
|
||||
@@ -207,8 +207,12 @@ pub fn writable_format_for_path(path: &str) -> Option<&'static str> {
|
||||
|
||||
pub fn format_for_path(path: &str) -> &'static str {
|
||||
let l = path.to_ascii_lowercase();
|
||||
if l.ends_with(".pptx") || l.ends_with(".potx") || l.ends_with(".ppsx") {
|
||||
if l.ends_with(".pptx") {
|
||||
"pptx"
|
||||
} else if l.ends_with(".potx") {
|
||||
"potx"
|
||||
} else if l.ends_with(".ppsx") {
|
||||
"ppsx"
|
||||
} else if l.ends_with(".png") {
|
||||
"png"
|
||||
} else if l.ends_with(".jpg") || l.ends_with(".jpeg") {
|
||||
|
||||
+12
-1
@@ -60,7 +60,18 @@ pub fn import(bytes: &[u8]) -> Result<Presentation, PptxError> {
|
||||
|
||||
/// Write a `.pptx` package.
|
||||
pub fn export(p: &Presentation) -> Result<Vec<u8>, PptxError> {
|
||||
write::export(p)
|
||||
write::export(p, write::CT_PRES)
|
||||
}
|
||||
|
||||
/// Write a package for `ext`: `potx` (template) and `ppsx` (slide show) differ from `pptx` only in
|
||||
/// the main part's content type.
|
||||
pub fn export_as(p: &Presentation, ext: &str) -> Result<Vec<u8>, PptxError> {
|
||||
let ct = match ext {
|
||||
"potx" => write::CT_TEMPLATE,
|
||||
"ppsx" => write::CT_SHOW,
|
||||
_ => write::CT_PRES,
|
||||
};
|
||||
write::export(p, ct)
|
||||
}
|
||||
|
||||
/// Content type for a file name's extension.
|
||||
|
||||
@@ -19,7 +19,9 @@ use crate::PptxError;
|
||||
use crate::opc::{self, NS_A, NS_P, NS_P14, NS_P188, NS_R, PackageOut, RelsOut};
|
||||
use crate::xml::{A, W};
|
||||
|
||||
const CT_PRES: &str = "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml";
|
||||
pub(crate) const CT_PRES: &str = "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml";
|
||||
pub(crate) const CT_TEMPLATE: &str = "application/vnd.openxmlformats-officedocument.presentationml.template.main+xml";
|
||||
pub(crate) const CT_SHOW: &str = "application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml";
|
||||
const CT_SLIDE: &str = "application/vnd.openxmlformats-officedocument.presentationml.slide+xml";
|
||||
const CT_LAYOUT: &str = "application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml";
|
||||
const CT_MASTER: &str = "application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml";
|
||||
@@ -418,7 +420,7 @@ fn sanitized(p: &Presentation) -> std::borrow::Cow<'_, Presentation> {
|
||||
std::borrow::Cow::Owned(q)
|
||||
}
|
||||
|
||||
pub fn export(p: &Presentation) -> Result<Vec<u8>, PptxError> {
|
||||
pub fn export(p: &Presentation, main_ct: &str) -> Result<Vec<u8>, PptxError> {
|
||||
let p = sanitized(p);
|
||||
let p: &Presentation = &p;
|
||||
let mut x = Exp {
|
||||
@@ -575,7 +577,7 @@ pub fn export(p: &Presentation) -> Result<Vec<u8>, PptxError> {
|
||||
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);
|
||||
x.pkg.xml_part("ppt/presentation.xml", CT_PRES, pxml);
|
||||
x.pkg.xml_part("ppt/presentation.xml", main_ct, pxml);
|
||||
x.pkg.rels("ppt/presentation.xml", &pres.rels);
|
||||
|
||||
// Document properties and package relationships.
|
||||
|
||||
@@ -1036,3 +1036,16 @@ fn linked_pictures_are_written_with_r_link() {
|
||||
std::io::Read::read_to_string(&mut zip.by_name("ppt/slides/_rels/slide1.xml.rels").expect("rels"), &mut rels).expect("read");
|
||||
assert!(rels.contains(r#"Target="file:///tmp/linked.png" TargetMode="External""#), "{rels}");
|
||||
}
|
||||
|
||||
/// #210: `.potx` and `.ppsx` were written with the `.pptx` main content type.
|
||||
#[test]
|
||||
fn templates_and_slide_shows_declare_their_own_main_content_type() {
|
||||
let p = rich_deck();
|
||||
for (ext, kind) in [("pptx", "presentation"), ("potx", "template"), ("ppsx", "slideshow")] {
|
||||
let bytes = deckcraft_pptx::export_as(&p, ext).expect("export");
|
||||
let mut z = zip::ZipArchive::new(std::io::Cursor::new(&bytes)).expect("zip");
|
||||
let ct = std::io::read_to_string(z.by_name("[Content_Types].xml").expect("content types")).expect("read");
|
||||
assert!(ct.contains(&format!("presentationml.{kind}.main+xml")), "{ext}: {ct}");
|
||||
assert_eq!(deckcraft_pptx::import(&bytes).expect("import").slides.len(), p.slides.len(), "{ext} reads back");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user