mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-26 11:26:50 -06:00
Merge branch 'pr-485' into batch/t5
This commit is contained in:
@@ -113,8 +113,58 @@ pub(crate) fn num(v: f64) -> String {
|
||||
}
|
||||
|
||||
/// `code` with every pixel length (`12px`) in rem of `root` pixels (`0.75rem`); names that end
|
||||
/// in "px" are left alone.
|
||||
/// in "px", markup lines (layer text), string literals and comments are left alone.
|
||||
pub fn px_to_rem(code: &str, root: f64) -> String {
|
||||
let mut out = String::with_capacity(code.len());
|
||||
let mut in_comment = false;
|
||||
for line in code.split_inclusive('\n') {
|
||||
if !in_comment && line.trim_start().starts_with('<') {
|
||||
out.push_str(line);
|
||||
continue;
|
||||
}
|
||||
// Lengths outside strings and comments convert; `plain` is where that stretch starts.
|
||||
let mut plain = 0;
|
||||
let mut chars = line.char_indices().peekable();
|
||||
while let Some((i, c)) = chars.next() {
|
||||
if in_comment {
|
||||
if c == '*' && chars.peek().is_some_and(|(_, n)| *n == '/') {
|
||||
chars.next();
|
||||
out.push_str(line.get(plain..i + 2).unwrap_or(""));
|
||||
plain = i + 2;
|
||||
in_comment = false;
|
||||
}
|
||||
} else if c == '/' && chars.peek().is_some_and(|(_, n)| *n == '*') {
|
||||
chars.next();
|
||||
out.push_str(&lengths_to_rem(line.get(plain..i).unwrap_or(""), root));
|
||||
plain = i;
|
||||
in_comment = true;
|
||||
} else if c == '"' {
|
||||
out.push_str(&lengths_to_rem(line.get(plain..i).unwrap_or(""), root));
|
||||
let mut end = line.len();
|
||||
while let Some((j, s)) = chars.next() {
|
||||
if s == '\\' {
|
||||
chars.next();
|
||||
} else if s == '"' {
|
||||
end = j + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
out.push_str(line.get(i..end).unwrap_or(""));
|
||||
plain = end;
|
||||
}
|
||||
}
|
||||
let rest = line.get(plain..).unwrap_or("");
|
||||
if in_comment {
|
||||
out.push_str(rest);
|
||||
} else {
|
||||
out.push_str(&lengths_to_rem(rest, root));
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
/// `code` with every pixel length in rem of `root` pixels; names that end in "px" are left alone.
|
||||
fn lengths_to_rem(code: &str, root: f64) -> String {
|
||||
let ident = |c: char| c.is_alphanumeric() || c == '_';
|
||||
let mut out = String::with_capacity(code.len());
|
||||
let mut rest = code;
|
||||
|
||||
@@ -77,3 +77,43 @@ fn leptos_wraps_the_markup_in_a_component_with_text_as_string_literals() {
|
||||
let out = s.execute("inspect.code", &json!({"id": card, "language": "leptos", "unit": "rem"})).unwrap();
|
||||
assert!(out["code"].as_str().unwrap().contains("width: 12.5rem;"), "{}", out["code"]);
|
||||
}
|
||||
|
||||
fn web_code(s: &mut Session, id: figcraft_doc::NodeId, language: &str, unit: &str) -> String {
|
||||
let out = s.execute("inspect.code", &json!({"id": id, "language": language, "unit": unit})).unwrap();
|
||||
out["code"].as_str().unwrap().to_string()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rem_preserves_text_in_web_markup() {
|
||||
let mut s = Session::new();
|
||||
let frame = id(s.execute("frame.create", &json!({"width": 200, "height": 100, "name": "Card"})).unwrap());
|
||||
s.execute("text.create", &json!({"text": "Tile 24px", "parent": frame, "name": "Label"})).unwrap();
|
||||
let mut changed = Vec::new();
|
||||
for language in ["html", "react", "leptos"] {
|
||||
let px = web_code(&mut s, frame, language, "px");
|
||||
let rem = web_code(&mut s, frame, language, "rem");
|
||||
assert!(px.contains("Tile 24px"), "{language}: px control: {px}");
|
||||
assert!(rem.contains("width: 12.5rem;"), "{language}: width: {rem}");
|
||||
assert!(rem.contains("font-size: 0.75rem;"), "{language}: font: {rem}");
|
||||
if !rem.contains("Tile 24px") {
|
||||
changed.push(language);
|
||||
}
|
||||
}
|
||||
assert!(changed.is_empty(), "text rewritten in {changed:?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rem_preserves_text_property_default() {
|
||||
let mut s = Session::new();
|
||||
let frame = id(s.execute("frame.create", &json!({"width": 100, "height": 40, "name": "Chip"})).unwrap());
|
||||
let label = id(s.execute("text.create", &json!({"text": "24px", "parent": frame, "name": "Label"})).unwrap());
|
||||
let component = id(s.execute("component.create", &json!({"ids": [frame]})).unwrap());
|
||||
s.execute("component.addProperty", &json!({"id": component, "name": "Label", "type": "text", "default": "24px", "layer": label})).unwrap();
|
||||
for unit in ["px", "rem"] {
|
||||
let code = web_code(&mut s, component, "react", unit);
|
||||
assert!(code.contains("label = \"24px\""), "{unit}: changed default: {code}");
|
||||
if unit == "rem" {
|
||||
assert!(code.contains("width: 6.25rem;"), "rem still converts lengths: {code}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user