Quote CSS font-family names that are not plain identifiers

Found while testing crates/svg/src/css.rs:112

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
NetterSilver
2026-10-21 15:20:11 +07:00
committed by bflatastic
co-authored by Claude Haiku 5.5
parent 2b0d71dbea
commit 7c8e772b46
+24 -5
View File
@@ -109,11 +109,10 @@ fn generic_fallback(family: &str) -> &'static str {
pub(crate) fn font_props(st: &CharStyle, len: &dyn Fn(f64) -> String) -> Props {
let mut p = Props::new();
// A quoted family escapes `\` and `'`, which would otherwise end the string early.
let fam = if st.font_family.contains(|c: char| c.is_whitespace() || matches!(c, ',' | '\'' | '\\')) {
format!("'{}'", st.font_family.replace('\\', "\\\\").replace('\'', "\\'"))
} else {
st.font_family.clone()
};
// Only a plain identifier (no leading digit) can be written bare; anything else is quoted.
let bare = st.font_family.chars().next().is_some_and(|c| !c.is_ascii_digit() && c != '-')
&& st.font_family.chars().all(|c| c.is_alphanumeric() || matches!(c, '-' | '_'));
let fam = if !bare { format!("'{}'", st.font_family.replace('\\', "\\\\").replace('\'', "\\'")) } else { st.font_family.clone() };
p.push(("font-family", format!("{fam}{}", generic_fallback(&st.font_family))));
p.push(("font-size", len(st.size * st.v_scale / 100.0)));
let (weight, italic) = font_descriptor(st);
@@ -695,3 +694,23 @@ fn is_upright_rectangle(path: &PathData) -> bool {
&& b.width() > 0.0
&& b.height() > 0.0
}
#[cfg(test)]
mod tests {
use super::*;
fn family(name: &str) -> String {
let st = CharStyle { font_family: name.into(), ..CharStyle::default() };
let p = font_props(&st, &|v| format!("{v}px"));
p.into_iter().find(|(k, _)| *k == "font-family").unwrap().1
}
#[test]
fn font_family_quoted_unless_plain_identifier() {
assert!(family("04b03").starts_with("'04b03'"), "{}", family("04b03"));
assert!(family("a;b").starts_with("'a;b'"));
assert!(family("a\"b").starts_with("'a\"b'"));
assert!(family("a(b").starts_with("'a(b'"));
assert!(family("Arial").starts_with("Arial,"));
}
}