mirror of
https://github.com/storytold/figcraft.git
synced 2026-11-03 00:39:44 -06:00
Escape backslashes and line breaks in CSS font-family export (#1752)
* Escape backslashes and line breaks in CSS font-family export Found while testing crates/engine/src/dev/codegen/css.rs:223 (text_decls, the font-family put) Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com> Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Escape quotes and < in CSS font-family export A double quote in a family name is escaped instead of turned into a single quote (CodeRabbit on #1752), and < is written as \3C so a name can't end the generated page's <style> block. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com> Co-authored-by: Brandon Thomas <echelon@gmail.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
Brandon Thomas
parent
fad47ac8bc
commit
45e5a25370
@@ -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() {
|
||||
|
||||
@@ -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 <style> block.
|
||||
let t = text(&mut s, "abc", json!({"fontFamily": "Foo\"</style>"}));
|
||||
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}");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user