diff --git a/crates/engine/src/score.rs b/crates/engine/src/score.rs index 847be67e..8f40fe5f 100644 --- a/crates/engine/src/score.rs +++ b/crates/engine/src/score.rs @@ -214,7 +214,13 @@ fn spell(pitch: u8) -> (char, i32, i32) { } fn xml_escape(s: &str) -> String { - s.replace('&', "&").replace('<', "<").replace('>', ">").replace('"', """) + s.chars() + .filter(|c| matches!(c, '\t' | '\n' | '\r' | '\u{20}'..='\u{D7FF}' | '\u{E000}'..='\u{FFFD}' | '\u{10000}'..='\u{10FFFF}')) + .collect::() + .replace('&', "&") + .replace('<', "<") + .replace('>', ">") + .replace('"', """) } fn note_type(units: u32) -> (&'static str, bool) { @@ -558,4 +564,19 @@ mod tests { let s = svg(&parts, &setup); assert!(s.starts_with(" = + out.chars().filter(|c| (*c < ' ' && !matches!(c, '\n' | '\t' | '\r')) || matches!(c, '\u{FFFE}' | '\u{FFFF}')).collect(); + assert!(bad.is_empty(), "forbidden characters: {bad:?}"); + } + } }