Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/great-shrimps-melt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@devup-ui/wasm": patch
---

Fix optimize value
13 changes: 13 additions & 0 deletions libs/css/src/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,24 @@ pub(super) static DOUBLE_SEPARATOR: phf::Set<&str> = phf_set! {
"view-transition-old",
};

pub(super) static ZERO_PERCENT_FUNCTION: phf::Set<&str> = phf_set! {
"min(",
"max(",
"clamp(",
"calc(",
"MIN(",
"MAX(",
"CLAMP(",
"CALC(",
};

pub(super) static F_SPACE_RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"\s*,\s*").unwrap());
pub(super) static F_DOT_RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"(\b|,)0\.(\d+)").unwrap());
pub(super) static DOT_ZERO_RE: Lazy<Regex> =
Lazy::new(|| Regex::new(r"(\b|,)-?0\.0+([^\d])").unwrap());

pub(super) static COLOR_HASH: Lazy<Regex> = Lazy::new(|| Regex::new(r"#([0-9a-zA-Z]+)").unwrap());
pub(super) static INNER_TRIM_RE: Lazy<Regex> =
Lazy::new(|| Regex::new(r"\(\s*([^)]*?)\s*\)").unwrap());
pub(super) static ZERO_RE: Lazy<Regex> =
Lazy::new(|| Regex::new(r"(^|\s|\(|,)-?0(px|em|rem|vh|vw|%|dvh|dvw)").unwrap());
67 changes: 66 additions & 1 deletion libs/css/src/optimize_value.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::{
COLOR_HASH, F_SPACE_RE, ZERO_RE,
constant::{DOT_ZERO_RE, F_DOT_RE},
constant::{DOT_ZERO_RE, F_DOT_RE, INNER_TRIM_RE, ZERO_PERCENT_FUNCTION},
};

pub fn optimize_value(value: &str) -> String {
let mut ret = value.trim().to_string();
ret = INNER_TRIM_RE.replace_all(&ret, "(${1})").to_string();
if ret.contains(",") {
ret = F_SPACE_RE.replace_all(&ret, ",").trim().to_string();
}
Expand All @@ -17,6 +18,31 @@ pub fn optimize_value(value: &str) -> String {
ret = DOT_ZERO_RE.replace_all(&ret, "${1}0${2}").to_string();
ret = F_DOT_RE.replace_all(&ret, "${1}.${2}").to_string();
ret = ZERO_RE.replace_all(&ret, "${1}0").to_string();

for f in ZERO_PERCENT_FUNCTION.iter() {
if ret.contains(f) {
let index = ret.find(f).unwrap() + f.len();
let mut zero_idx = vec![];
let mut depth = 0;
for i in index..ret.len() {
if ret[i..i + 1].eq("(") {
depth += 1;
} else if ret[i..i + 1].eq(")") {
depth -= 1;
} else if ret[i..i + 1].eq("0")
&& !ret[i - 1..i].chars().next().unwrap().is_ascii_digit()
&& (ret.len() == i + 1
|| !ret[i + 1..i + 2].chars().next().unwrap().is_ascii_digit())
&& depth == 0
{
zero_idx.push(i);
}
}
for i in zero_idx.iter().rev() {
ret = ret[..*i].to_string() + "0%" + &ret[*i + 1..];
}
}
}
}
// remove ; from dynamic value
for str_symbol in ["", "`", "\"", "'"] {
Expand All @@ -34,6 +60,27 @@ pub fn optimize_value(value: &str) -> String {
);
}
}

if ret.contains("(") || ret.contains(")") {
let mut depth = 0;
for i in 0..ret.len() {
if ret[i..i + 1].eq("(") {
depth += 1;
} else if ret[i..i + 1].eq(")") {
depth -= 1;
}
}
if depth < 0 {
for _ in 0..(-depth) {
ret.insert(0, '(');
}
}
if depth > 0 {
for _ in 0..depth {
ret.push(')');
}
}
}
ret
}

Expand Down Expand Up @@ -99,6 +146,19 @@ mod tests {
#[case("translate(-0px, 0px)", "translate(0,0)")]
#[case("translate(0px, 0px)", "translate(0,0)")]
#[case("translate(10px, 0px)", "translate(10px,0)")]
#[case("translate( 10px , 0px )", "translate(10px,0)")]
#[case("translate( 0px , 0px )", "translate(0,0)")]
#[case(" translate( 0px , 0px ) ", "translate(0,0)")]
#[case("clamp(0, 10px, 10px)", "clamp(0%,10px,10px)")]
#[case("clamp(10px, 0, 10px)", "clamp(10px,0%,10px)")]
#[case("clamp(10px, 10px, 0)", "clamp(10px,10px,0%)")]
#[case("clamp(0px, 10px, 0px)", "clamp(0%,10px,0%)")]
#[case("min(0, 10px)", "min(0%,10px)")]
#[case("max(0, 10px)", "max(0%,10px)")]
#[case("min(10px, 0)", "min(10px,0%)")]
#[case("max(10px, 0)", "max(10px,0%)")]
#[case("max(some(0), 0)", "max(some(0),0%)")]
#[case("translate(0, min(0, 10px))", "translate(0,min(0%,10px))")]
#[case("\"red\"", "\"red\"")]
#[case("'red'", "'red'")]
#[case("`red`", "`red`")]
Expand All @@ -110,6 +170,11 @@ mod tests {
#[case("('red;')", "('red')")]
#[case("('red') + 'blue;'", "('red') + 'blue'")]
#[case("translateX(0px) translateY(0px)", "translateX(0) translateY(0)")]
// recovery case
#[case("max(10px, 0", "max(10px,0%)")]
#[case("max(10px, calc(0", "max(10px,calc(0%))")]
#[case("max(10px, any(0", "max(10px,any(0))")]
#[case("10px, any(0))", "(10px,any(0))")]
fn test_optimize_value(#[case] input: &str, #[case] expected: &str) {
assert_eq!(optimize_value(input), expected);
}
Expand Down
1 change: 0 additions & 1 deletion libs/css/src/property_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ impl From<[&str; 2]> for PropertyType {
}

#[cfg(test)]

mod tests {

use super::*;
Expand Down
6 changes: 3 additions & 3 deletions libs/css/src/style_selector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ impl Display for StyleSelector {
format!("@{query}")
}
}
StyleSelector::Global(value, _) => format!("{value}"),
StyleSelector::Global(value, _) => value.to_string(),
}
)
}
Expand Down Expand Up @@ -296,7 +296,7 @@ mod tests {
#[case(
StyleSelector::Global("div:hover".to_string(), "file2.rs".to_string()),
StyleSelector::Global("span:hover".to_string(), "file1.rs".to_string()),
"div".cmp(&"span")
"div".cmp("span")
)]
#[case(
StyleSelector::Global("div:hover".to_string(), "file2.rs".to_string()),
Expand All @@ -306,7 +306,7 @@ mod tests {
#[case(
StyleSelector::Global("div:".to_string(), "file2.rs".to_string()),
StyleSelector::Global("span:".to_string(), "file1.rs".to_string()),
"div".cmp(&"span")
"div".cmp("span")
)]
// global selector always less than selector
#[case(
Expand Down
11 changes: 5 additions & 6 deletions libs/extractor/src/css_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub fn css_to_style<'a>(
if s.is_empty() {
return None;
}
Some(format!("@media{}", s))
Some(format!("@media{s}"))
})
.collect::<Vec<_>>();
if media_inputs.len() > 1 {
Expand Down Expand Up @@ -69,9 +69,9 @@ pub fn css_to_style<'a>(
}
};
let block = if block.contains('{') {
css_to_style(block, level, &sel)
css_to_style(block, level, sel)
} else {
css_to_style_block(block, level, &sel)
css_to_style_block(block, level, sel)
};
let input_end = input.rfind('}').unwrap() + 1;

Expand All @@ -98,7 +98,7 @@ fn css_to_style_block<'a>(
selector: &Option<StyleSelector>,
) -> Vec<ExtractStyleProp<'a>> {
css.split(";")
.map(|s| {
.filter_map(|s| {
let s = s.trim();
if s.is_empty() {
None
Expand All @@ -111,7 +111,6 @@ fn css_to_style_block<'a>(
)))
}
})
.flatten()
.collect()
}

Expand Down Expand Up @@ -163,7 +162,7 @@ pub fn optimize_css_block(css: &str) -> String {
let mut iter = s.split(":");
let property = iter.next().unwrap().trim();
let value = iter.next().unwrap().trim();
format!("{}:{}", property, value)
format!("{property}:{value}")
}
})
.collect::<Vec<String>>()
Expand Down
4 changes: 2 additions & 2 deletions libs/extractor/src/extract_style/extract_style_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,12 @@ mod tests {
css: "".to_string(),
file: "".to_string(),
});
assert!(matches!(value.extract(), None));
assert!(value.extract().is_none());

let value = ExtractStyleValue::Import(ExtractImport {
url: "".to_string(),
file: "".to_string(),
});
assert!(matches!(value.extract(), None));
assert!(value.extract().is_none());
}
}
10 changes: 6 additions & 4 deletions libs/extractor/src/extract_style/style_property.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::fmt::{Display, Error, Formatter};

pub enum StyleProperty {
ClassName(String),
Variable {
Expand All @@ -6,11 +8,11 @@ pub enum StyleProperty {
identifier: String,
},
}
impl StyleProperty {
pub fn to_string(&self) -> String {
impl Display for StyleProperty {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
match self {
StyleProperty::ClassName(name) => name.clone(),
StyleProperty::Variable { variable_name, .. } => format!("var({})", variable_name),
StyleProperty::ClassName(name) => write!(f, "{name}"),
StyleProperty::Variable { variable_name, .. } => write!(f, "var({variable_name})"),
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions libs/extractor/src/extractor/extract_style_from_expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ pub fn extract_style_from_expression<'a>(
.collect::<Vec<_>>()
.join(""),
level,
&selector,
selector,
),
..ExtractResult::default()
},
Expand Down Expand Up @@ -228,7 +228,7 @@ pub fn extract_style_from_expression<'a>(
}
} else {
ExtractResult {
styles: css_to_style(&value, level, &selector),
styles: css_to_style(&value, level, selector),
..ExtractResult::default()
}
}
Expand Down
8 changes: 4 additions & 4 deletions libs/extractor/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,8 @@ impl<'a> VisitMut<'a> for DevupVisitor<'a> {
let keyframes = ExtractKeyframes {
keyframes: keyframes_to_keyframes_style(&css_str)
.into_iter()
.filter_map(|(k, v)| {
Some((
.map(|(k, v)| {
(
k,
v.into_iter()
.filter_map(|ex| {
Expand All @@ -270,7 +270,7 @@ impl<'a> VisitMut<'a> for DevupVisitor<'a> {
}
})
.collect(),
))
)
})
.collect(),
};
Expand Down Expand Up @@ -354,7 +354,7 @@ impl<'a> VisitMut<'a> for DevupVisitor<'a> {
kind.extract()
.into_iter()
.rev()
.map(|ex| ExtractStyleProp::Static(ex)),
.map(ExtractStyleProp::Static),
);
props_styles.iter().rev().for_each(|style| {
self.styles.extend(style.extract().into_iter().map(|mut s| {
Expand Down
10 changes: 5 additions & 5 deletions libs/sheet/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,8 @@ impl StyleSheet {
}
self.global_css_files.remove(file);
self.css.remove(file);
for (_, map) in self.properties.iter_mut() {
for (_, props) in map.iter_mut() {
for map in self.properties.values_mut() {
for props in map.values_mut() {
props.retain(|prop| {
if let Some(StyleSelector::Global(_, f)) = prop.selector.as_ref() {
f != file
Expand Down Expand Up @@ -265,7 +265,7 @@ impl StyleSheet {
color_interface_name,
color_keys
.into_iter()
.map(|key| format!("{}:null;", convert_interface_key(&format!("${}", key))))
.map(|key| format!("{}:null;", convert_interface_key(&format!("${key}"))))
.collect::<Vec<String>>()
.join(""),
typography_interface_name,
Expand All @@ -288,8 +288,8 @@ impl StyleSheet {
pub fn create_css(&self) -> String {
let mut css = self
.imports
.iter()
.map(|(_, import)| format!("@import \"{}\";", import))
.values()
.map(|import| format!("@import \"{import}\";"))
.collect::<Vec<String>>()
.join("");
css.push_str(&self.theme.to_css());
Expand Down
13 changes: 9 additions & 4 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
packages:
- 'packages/*'
- 'apps/*'
- 'bindings/*'
- 'benchmark/*'
- packages/*
- apps/*
- bindings/*
- benchmark/*

onlyBuiltDependencies:
- core-js
- esbuild
- sharp