Skip to content

Commit 469edf8

Browse files
committed
Fix optimize value
1 parent c677621 commit 469edf8

File tree

12 files changed

+118
-30
lines changed

12 files changed

+118
-30
lines changed

.changeset/great-shrimps-melt.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@devup-ui/wasm": patch
3+
---
4+
5+
Fix optimize value

libs/css/src/constant.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,24 @@ pub(super) static DOUBLE_SEPARATOR: phf::Set<&str> = phf_set! {
7676
"view-transition-old",
7777
};
7878

79+
pub(super) static ZERO_PERCENT_FUNCTION: phf::Set<&str> = phf_set! {
80+
"min(",
81+
"max(",
82+
"clamp(",
83+
"calc(",
84+
"MIN(",
85+
"MAX(",
86+
"CLAMP(",
87+
"CALC(",
88+
};
89+
7990
pub(super) static F_SPACE_RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"\s*,\s*").unwrap());
8091
pub(super) static F_DOT_RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"(\b|,)0\.(\d+)").unwrap());
8192
pub(super) static DOT_ZERO_RE: Lazy<Regex> =
8293
Lazy::new(|| Regex::new(r"(\b|,)-?0\.0+([^\d])").unwrap());
8394

8495
pub(super) static COLOR_HASH: Lazy<Regex> = Lazy::new(|| Regex::new(r"#([0-9a-zA-Z]+)").unwrap());
96+
pub(super) static INNER_TRIM_RE: Lazy<Regex> =
97+
Lazy::new(|| Regex::new(r"\(\s*([^)]*?)\s*\)").unwrap());
8598
pub(super) static ZERO_RE: Lazy<Regex> =
8699
Lazy::new(|| Regex::new(r"(^|\s|\(|,)-?0(px|em|rem|vh|vw|%|dvh|dvw)").unwrap());

libs/css/src/optimize_value.rs

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
use crate::{
22
COLOR_HASH, F_SPACE_RE, ZERO_RE,
3-
constant::{DOT_ZERO_RE, F_DOT_RE},
3+
constant::{DOT_ZERO_RE, F_DOT_RE, INNER_TRIM_RE, ZERO_PERCENT_FUNCTION},
44
};
55

66
pub fn optimize_value(value: &str) -> String {
77
let mut ret = value.trim().to_string();
8+
ret = INNER_TRIM_RE.replace_all(&ret, "(${1})").to_string();
89
if ret.contains(",") {
910
ret = F_SPACE_RE.replace_all(&ret, ",").trim().to_string();
1011
}
@@ -17,6 +18,31 @@ pub fn optimize_value(value: &str) -> String {
1718
ret = DOT_ZERO_RE.replace_all(&ret, "${1}0${2}").to_string();
1819
ret = F_DOT_RE.replace_all(&ret, "${1}.${2}").to_string();
1920
ret = ZERO_RE.replace_all(&ret, "${1}0").to_string();
21+
22+
for f in ZERO_PERCENT_FUNCTION.iter() {
23+
if ret.contains(f) {
24+
let index = ret.find(f).unwrap() + f.len();
25+
let mut zero_idx = vec![];
26+
let mut depth = 0;
27+
for i in index..ret.len() {
28+
if ret[i..i + 1].eq("(") {
29+
depth += 1;
30+
} else if ret[i..i + 1].eq(")") {
31+
depth -= 1;
32+
} else if ret[i..i + 1].eq("0")
33+
&& !ret[i - 1..i].chars().next().unwrap().is_ascii_digit()
34+
&& (ret.len() == i + 1
35+
|| !ret[i + 1..i + 2].chars().next().unwrap().is_ascii_digit())
36+
&& depth == 0
37+
{
38+
zero_idx.push(i);
39+
}
40+
}
41+
for i in zero_idx.iter().rev() {
42+
ret = ret[..*i].to_string() + "0%" + &ret[*i + 1..];
43+
}
44+
}
45+
}
2046
}
2147
// remove ; from dynamic value
2248
for str_symbol in ["", "`", "\"", "'"] {
@@ -34,6 +60,27 @@ pub fn optimize_value(value: &str) -> String {
3460
);
3561
}
3662
}
63+
64+
if ret.contains("(") || ret.contains(")") {
65+
let mut depth = 0;
66+
for i in 0..ret.len() {
67+
if ret[i..i + 1].eq("(") {
68+
depth += 1;
69+
} else if ret[i..i + 1].eq(")") {
70+
depth -= 1;
71+
}
72+
}
73+
if depth < 0 {
74+
for _ in 0..(-depth) {
75+
ret.insert(0, '(');
76+
}
77+
}
78+
if depth > 0 {
79+
for _ in 0..depth {
80+
ret.push(')');
81+
}
82+
}
83+
}
3784
ret
3885
}
3986

@@ -99,6 +146,19 @@ mod tests {
99146
#[case("translate(-0px, 0px)", "translate(0,0)")]
100147
#[case("translate(0px, 0px)", "translate(0,0)")]
101148
#[case("translate(10px, 0px)", "translate(10px,0)")]
149+
#[case("translate( 10px , 0px )", "translate(10px,0)")]
150+
#[case("translate( 0px , 0px )", "translate(0,0)")]
151+
#[case(" translate( 0px , 0px ) ", "translate(0,0)")]
152+
#[case("clamp(0, 10px, 10px)", "clamp(0%,10px,10px)")]
153+
#[case("clamp(10px, 0, 10px)", "clamp(10px,0%,10px)")]
154+
#[case("clamp(10px, 10px, 0)", "clamp(10px,10px,0%)")]
155+
#[case("clamp(0px, 10px, 0px)", "clamp(0%,10px,0%)")]
156+
#[case("min(0, 10px)", "min(0%,10px)")]
157+
#[case("max(0, 10px)", "max(0%,10px)")]
158+
#[case("min(10px, 0)", "min(10px,0%)")]
159+
#[case("max(10px, 0)", "max(10px,0%)")]
160+
#[case("max(some(0), 0)", "max(some(0),0%)")]
161+
#[case("translate(0, min(0, 10px))", "translate(0,min(0%,10px))")]
102162
#[case("\"red\"", "\"red\"")]
103163
#[case("'red'", "'red'")]
104164
#[case("`red`", "`red`")]
@@ -110,6 +170,11 @@ mod tests {
110170
#[case("('red;')", "('red')")]
111171
#[case("('red') + 'blue;'", "('red') + 'blue'")]
112172
#[case("translateX(0px) translateY(0px)", "translateX(0) translateY(0)")]
173+
// recovery case
174+
#[case("max(10px, 0", "max(10px,0%)")]
175+
#[case("max(10px, calc(0", "max(10px,calc(0%))")]
176+
#[case("max(10px, any(0", "max(10px,any(0))")]
177+
#[case("10px, any(0))", "(10px,any(0))")]
113178
fn test_optimize_value(#[case] input: &str, #[case] expected: &str) {
114179
assert_eq!(optimize_value(input), expected);
115180
}

libs/css/src/property_type.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ impl From<[&str; 2]> for PropertyType {
4141
}
4242

4343
#[cfg(test)]
44-
4544
mod tests {
4645

4746
use super::*;

libs/css/src/style_selector.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ impl Display for StyleSelector {
171171
format!("@{query}")
172172
}
173173
}
174-
StyleSelector::Global(value, _) => format!("{value}"),
174+
StyleSelector::Global(value, _) => value.to_string(),
175175
}
176176
)
177177
}
@@ -296,7 +296,7 @@ mod tests {
296296
#[case(
297297
StyleSelector::Global("div:hover".to_string(), "file2.rs".to_string()),
298298
StyleSelector::Global("span:hover".to_string(), "file1.rs".to_string()),
299-
"div".cmp(&"span")
299+
"div".cmp("span")
300300
)]
301301
#[case(
302302
StyleSelector::Global("div:hover".to_string(), "file2.rs".to_string()),
@@ -306,7 +306,7 @@ mod tests {
306306
#[case(
307307
StyleSelector::Global("div:".to_string(), "file2.rs".to_string()),
308308
StyleSelector::Global("span:".to_string(), "file1.rs".to_string()),
309-
"div".cmp(&"span")
309+
"div".cmp("span")
310310
)]
311311
// global selector always less than selector
312312
#[case(

libs/extractor/src/css_utils.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub fn css_to_style<'a>(
2525
if s.is_empty() {
2626
return None;
2727
}
28-
Some(format!("@media{}", s))
28+
Some(format!("@media{s}"))
2929
})
3030
.collect::<Vec<_>>();
3131
if media_inputs.len() > 1 {
@@ -69,9 +69,9 @@ pub fn css_to_style<'a>(
6969
}
7070
};
7171
let block = if block.contains('{') {
72-
css_to_style(block, level, &sel)
72+
css_to_style(block, level, sel)
7373
} else {
74-
css_to_style_block(block, level, &sel)
74+
css_to_style_block(block, level, sel)
7575
};
7676
let input_end = input.rfind('}').unwrap() + 1;
7777

@@ -98,7 +98,7 @@ fn css_to_style_block<'a>(
9898
selector: &Option<StyleSelector>,
9999
) -> Vec<ExtractStyleProp<'a>> {
100100
css.split(";")
101-
.map(|s| {
101+
.filter_map(|s| {
102102
let s = s.trim();
103103
if s.is_empty() {
104104
None
@@ -111,7 +111,6 @@ fn css_to_style_block<'a>(
111111
)))
112112
}
113113
})
114-
.flatten()
115114
.collect()
116115
}
117116

@@ -163,7 +162,7 @@ pub fn optimize_css_block(css: &str) -> String {
163162
let mut iter = s.split(":");
164163
let property = iter.next().unwrap().trim();
165164
let value = iter.next().unwrap().trim();
166-
format!("{}:{}", property, value)
165+
format!("{property}:{value}")
167166
}
168167
})
169168
.collect::<Vec<String>>()

libs/extractor/src/extract_style/extract_style_value.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,12 @@ mod tests {
8585
css: "".to_string(),
8686
file: "".to_string(),
8787
});
88-
assert!(matches!(value.extract(), None));
88+
assert!(value.extract().is_none());
8989

9090
let value = ExtractStyleValue::Import(ExtractImport {
9191
url: "".to_string(),
9292
file: "".to_string(),
9393
});
94-
assert!(matches!(value.extract(), None));
94+
assert!(value.extract().is_none());
9595
}
9696
}

libs/extractor/src/extract_style/style_property.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::fmt::{Display, Error, Formatter};
2+
13
pub enum StyleProperty {
24
ClassName(String),
35
Variable {
@@ -6,11 +8,11 @@ pub enum StyleProperty {
68
identifier: String,
79
},
810
}
9-
impl StyleProperty {
10-
pub fn to_string(&self) -> String {
11+
impl Display for StyleProperty {
12+
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
1113
match self {
12-
StyleProperty::ClassName(name) => name.clone(),
13-
StyleProperty::Variable { variable_name, .. } => format!("var({})", variable_name),
14+
StyleProperty::ClassName(name) => write!(f, "{name}"),
15+
StyleProperty::Variable { variable_name, .. } => write!(f, "var({variable_name})"),
1416
}
1517
}
1618
}

libs/extractor/src/extractor/extract_style_from_expression.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ pub fn extract_style_from_expression<'a>(
144144
.collect::<Vec<_>>()
145145
.join(""),
146146
level,
147-
&selector,
147+
selector,
148148
),
149149
..ExtractResult::default()
150150
},
@@ -228,7 +228,7 @@ pub fn extract_style_from_expression<'a>(
228228
}
229229
} else {
230230
ExtractResult {
231-
styles: css_to_style(&value, level, &selector),
231+
styles: css_to_style(&value, level, selector),
232232
..ExtractResult::default()
233233
}
234234
}

libs/extractor/src/visit.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -255,8 +255,8 @@ impl<'a> VisitMut<'a> for DevupVisitor<'a> {
255255
let keyframes = ExtractKeyframes {
256256
keyframes: keyframes_to_keyframes_style(&css_str)
257257
.into_iter()
258-
.filter_map(|(k, v)| {
259-
Some((
258+
.map(|(k, v)| {
259+
(
260260
k,
261261
v.into_iter()
262262
.filter_map(|ex| {
@@ -270,7 +270,7 @@ impl<'a> VisitMut<'a> for DevupVisitor<'a> {
270270
}
271271
})
272272
.collect(),
273-
))
273+
)
274274
})
275275
.collect(),
276276
};
@@ -354,7 +354,7 @@ impl<'a> VisitMut<'a> for DevupVisitor<'a> {
354354
kind.extract()
355355
.into_iter()
356356
.rev()
357-
.map(|ex| ExtractStyleProp::Static(ex)),
357+
.map(ExtractStyleProp::Static),
358358
);
359359
props_styles.iter().rev().for_each(|style| {
360360
self.styles.extend(style.extract().into_iter().map(|mut s| {

0 commit comments

Comments
 (0)