diff --git a/crates/engine/src/dev/codegen/css.rs b/crates/engine/src/dev/codegen/css.rs index b418e771f..0e07f0bf1 100644 --- a/crates/engine/src/dev/codegen/css.rs +++ b/crates/engine/src/dev/codegen/css.rs @@ -220,7 +220,19 @@ fn effect_decls(n: &Node, put: &mut impl FnMut(&str, String)) { fn text_decls(doc: &Document, n: &Node, tx: &figcraft_doc::TextData, t: &mut Tokens, put: &mut impl FnMut(&str, String)) { let px = |v: f64| format!("{}px", num(v)); let s = &tx.style; - put("font-family", tok(doc, n, &["fontFamily"], format!("\"{}\"", s.font_family.replace('"', "'")), t)); + put( + "font-family", + tok( + doc, + n, + &["fontFamily"], + format!( + "\"{}\"", + s.font_family.replace('\\', "\\\\").replace('"', "\\\"").replace('<', "\\3C ").replace("\r\n", "\\A ").replace(['\n', '\r'], "\\A ") + ), + t, + ), + ); put("font-size", tok(doc, n, &["fontSize"], px(s.font_size), t)); put("font-weight", s.weight().to_string()); if s.italic() { diff --git a/crates/engine/src/text_behaviour_tests.rs b/crates/engine/src/text_behaviour_tests.rs index eac41f518..b263211ee 100644 --- a/crates/engine/src/text_behaviour_tests.rs +++ b/crates/engine/src/text_behaviour_tests.rs @@ -535,3 +535,18 @@ fn auto_layout_places_right_aligned_auto_width_text() { let c = s.doc().unwrap().node(t).unwrap().transform.as_coeffs(); assert_eq!((c[4], c[5]), (10.0, 10.0), "the auto layout keeps it at its padding"); } + +#[test] +fn css_font_family_escapes_backslash_and_newline() { + let mut s = Session::new(); + let t = text(&mut s, "abc", json!({"fontFamily": "Foo\\"})); + let css = crate::codegen::css_decls(s.doc().unwrap(), s.doc().unwrap().node(t).unwrap(), &mut Default::default(), (true, true)); + assert!(css.contains(r#"font-family: "Foo\\";"#), "{css}"); + let t = text(&mut s, "abc", json!({"fontFamily": "Foo\nBar"})); + let css = crate::codegen::css_decls(s.doc().unwrap(), s.doc().unwrap().node(t).unwrap(), &mut Default::default(), (true, true)); + assert!(css.contains(r#"font-family: "Foo\A Bar";"#), "{css}"); + // A quote stays a quote, and a name can't close the page's "})); + let css = crate::codegen::css_decls(s.doc().unwrap(), s.doc().unwrap().node(t).unwrap(), &mut Default::default(), (true, true)); + assert!(css.contains(r#"font-family: "Foo\"\3C /style>";"#), "{css}"); +}