mirror of
https://github.com/storytold/deckcraft.git
synced 2026-10-24 10:37:03 -06:00
Declare the a: and r: namespaces on the modern comments part (#974)
p188:cmLst declared only xmlns:p188 but its comment bodies use a:bodyPr, a:p, a:r and a:t, so the part was not namespace-well-formed and PowerPoint refused the saved file. A regression test parses every written XML part with a namespace-aware reader. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
22db9261f9
commit
601823d98c
@@ -876,7 +876,7 @@ fn author_slot(c: &Comment, authors: &mut Vec<(String, String, u32)>) -> usize {
|
||||
/// the flattened legacy part cannot express (issue #70).
|
||||
fn modern_comments_xml(list: &[Comment], part: &str, authors: &mut Vec<(String, String, u32)>) -> Vec<u8> {
|
||||
let mut w = W::new();
|
||||
w.open("p188:cmLst", A::new().a("xmlns:p188", NS_P188));
|
||||
w.open("p188:cmLst", A::new().a("xmlns:p188", NS_P188).a("xmlns:a", NS_A).a("xmlns:r", NS_R));
|
||||
for (ti, c) in list.iter().take(10_000).enumerate() {
|
||||
modern_comment(&mut w, c, part, ti, authors, 0);
|
||||
}
|
||||
|
||||
@@ -206,3 +206,37 @@ fn modern_only_package_imports() {
|
||||
assert!(b[0].resolved);
|
||||
assert_eq!((b[0].x, b[0].y), (90.0, 45.0), "modern positions are EMU");
|
||||
}
|
||||
|
||||
/// Every prefix an exported part uses is bound: PowerPoint refuses a package whose part is not
|
||||
/// namespace-well-formed (issue #974, the modern comments part used `a:` without declaring it).
|
||||
#[test]
|
||||
fn every_written_xml_part_binds_its_prefixes() {
|
||||
use quick_xml::events::Event;
|
||||
use quick_xml::name::ResolveResult;
|
||||
|
||||
let bytes = deckcraft_pptx::export(&deck()).expect("export");
|
||||
let mut z = zip::ZipArchive::new(std::io::Cursor::new(&bytes)).expect("zip");
|
||||
let mut modern = 0;
|
||||
for i in 0..z.len() {
|
||||
let mut f = z.by_index(i).expect("entry");
|
||||
let name = f.name().to_string();
|
||||
if !(name.ends_with(".xml") || name.ends_with(".rels")) {
|
||||
continue;
|
||||
}
|
||||
let mut data = vec![];
|
||||
f.read_to_end(&mut data).expect("read");
|
||||
modern += usize::from(name.contains("modernComment"));
|
||||
let mut r = quick_xml::NsReader::from_reader(data.as_slice());
|
||||
loop {
|
||||
match r.read_resolved_event() {
|
||||
Ok((ns, Event::Start(e) | Event::Empty(e))) => {
|
||||
assert!(!matches!(ns, ResolveResult::Unknown(_)), "{name}: unbound prefix on <{}>", String::from_utf8_lossy(e.name().as_ref()));
|
||||
}
|
||||
Ok((_, Event::Eof)) => break,
|
||||
Ok(_) => {}
|
||||
Err(e) => panic!("{name}: not well-formed: {e}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
assert!(modern > 0, "the deck should write a modern comments part");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user