Skip to content

Commit

Permalink
feat(css/prefixer): Support clamp (#6695)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexander-akait committed Dec 27, 2022
1 parent d72a31f commit 1722428
Show file tree
Hide file tree
Showing 5 changed files with 215 additions and 10 deletions.
10 changes: 10 additions & 0 deletions crates/swc_css_prefixer/data/prefixes_and_browsers.json
Expand Up @@ -3294,6 +3294,16 @@
"samsung": "4"
}
],
"clamp()": [
{
"safari": "11.1",
"ios": "11.3"
},
{
"safari": "13",
"ios": "13.3"
}
],

"-webkit-image-set()": [
{
Expand Down
86 changes: 76 additions & 10 deletions crates/swc_css_prefixer/src/prefixer.rs
Expand Up @@ -115,7 +115,7 @@ pub fn prefixer(options: Options) -> impl VisitMut {
}
}

pub struct CrossFadeFunctionReplacerOnLegacyVariant<'a> {
struct CrossFadeFunctionReplacerOnLegacyVariant<'a> {
from: &'a str,
to: &'a str,
}
Expand Down Expand Up @@ -228,14 +228,14 @@ impl VisitMut for CrossFadeFunctionReplacerOnLegacyVariant<'_> {
}
}

pub fn replace_cross_fade_function_on_legacy_variant<N>(node: &mut N, from: &str, to: &str)
fn replace_cross_fade_function_on_legacy_variant<N>(node: &mut N, from: &str, to: &str)
where
N: for<'aa> VisitMutWith<CrossFadeFunctionReplacerOnLegacyVariant<'aa>>,
{
node.visit_mut_with(&mut CrossFadeFunctionReplacerOnLegacyVariant { from, to });
}

pub struct ImageSetFunctionReplacerOnLegacyVariant<'a> {
struct ImageSetFunctionReplacerOnLegacyVariant<'a> {
from: &'a str,
to: &'a str,
in_function: bool,
Expand Down Expand Up @@ -291,7 +291,7 @@ impl VisitMut for ImageSetFunctionReplacerOnLegacyVariant<'_> {
}
}

pub fn replace_image_set_function_on_legacy_variant<N>(node: &mut N, from: &str, to: &str)
fn replace_image_set_function_on_legacy_variant<N>(node: &mut N, from: &str, to: &str)
where
N: for<'aa> VisitMutWith<ImageSetFunctionReplacerOnLegacyVariant<'aa>>,
{
Expand All @@ -302,7 +302,7 @@ where
});
}

pub struct LinearGradientFunctionReplacerOnLegacyVariant<'a> {
struct LinearGradientFunctionReplacerOnLegacyVariant<'a> {
from: &'a str,
to: &'a str,
}
Expand Down Expand Up @@ -478,14 +478,14 @@ impl VisitMut for LinearGradientFunctionReplacerOnLegacyVariant<'_> {
}
}

pub fn replace_gradient_function_on_legacy_variant<N>(node: &mut N, from: &str, to: &str)
fn replace_gradient_function_on_legacy_variant<N>(node: &mut N, from: &str, to: &str)
where
N: for<'aa> VisitMutWith<LinearGradientFunctionReplacerOnLegacyVariant<'aa>>,
{
node.visit_mut_with(&mut LinearGradientFunctionReplacerOnLegacyVariant { from, to });
}

pub struct MediaFeatureResolutionReplacerOnLegacyVariant<'a> {
struct MediaFeatureResolutionReplacerOnLegacyVariant<'a> {
from: &'a str,
to: &'a str,
}
Expand Down Expand Up @@ -531,7 +531,7 @@ impl VisitMut for MediaFeatureResolutionReplacerOnLegacyVariant<'_> {
}
}

pub fn replace_media_feature_resolution_on_legacy_variant<N>(node: &mut N, from: &str, to: &str)
fn replace_media_feature_resolution_on_legacy_variant<N>(node: &mut N, from: &str, to: &str)
where
N: for<'aa> VisitMutWith<MediaFeatureResolutionReplacerOnLegacyVariant<'aa>>,
{
Expand Down Expand Up @@ -622,7 +622,7 @@ where
});
}

pub struct FontFaceFormatOldSyntax {}
struct FontFaceFormatOldSyntax {}

impl VisitMut for FontFaceFormatOldSyntax {
fn visit_mut_function(&mut self, n: &mut Function) {
Expand Down Expand Up @@ -662,13 +662,75 @@ impl VisitMut for FontFaceFormatOldSyntax {
}
}

pub fn font_face_format_old_syntax<N>(node: &mut N)
fn font_face_format_old_syntax<N>(node: &mut N)
where
N: VisitMutWith<FontFaceFormatOldSyntax>,
{
node.visit_mut_with(&mut FontFaceFormatOldSyntax {});
}

struct ClampReplacer {}

impl VisitMut for ClampReplacer {
fn visit_mut_function(&mut self, n: &mut Function) {
n.visit_mut_children_with(self);

if n.name != js_word!("clamp") {
return;
}

let min_function = if let (
Some(middle @ ComponentValue::CalcSum(_)),
Some(comma),
Some(right @ ComponentValue::CalcSum(_)),
) = (n.value.get(2), n.value.get(3), n.value.get(4))
{
Function {
span: n.span,
name: FunctionName::Ident(Ident {
span: n.span,
value: js_word!("min"),
raw: None,
}),
value: vec![middle.clone(), comma.clone(), right.clone()],
}
} else {
return;
};

if let (Some(left), Some(comma)) = (n.value.get(0), n.value.get(1)) {
*n = Function {
span: n.span,
name: FunctionName::Ident(Ident {
span: n.span,
value: js_word!("max"),
raw: None,
}),
value: vec![
left.clone(),
comma.clone(),
ComponentValue::CalcSum(Box::new(CalcSum {
span: DUMMY_SP,
expressions: vec![CalcProductOrOperator::Product(CalcProduct {
span: DUMMY_SP,
expressions: vec![CalcValueOrOperator::Value(CalcValue::Function(
min_function,
))],
})],
})),
],
};
}
}
}

fn replace_clamp<N>(node: &mut N)
where
N: VisitMutWith<ClampReplacer>,
{
node.visit_mut_with(&mut ClampReplacer {});
}

macro_rules! to_ident {
($val:expr) => {{
ComponentValue::Ident(Box::new(Ident {
Expand Down Expand Up @@ -1449,6 +1511,10 @@ impl VisitMut for Prefixer {
"-webkit-repeating-radial-gradient",
);
}

if should_prefix("clamp()", self.env, true) {
replace_clamp(&mut webkit_value);
}
}

let mut moz_value = n.value.clone();
Expand Down
44 changes: 44 additions & 0 deletions crates/swc_css_prefixer/tests/fixture/clamp/input.css
@@ -0,0 +1,44 @@
a {
width: clamp(10px, 64px, 80px);
}

a {
width: clamp(calc(100% - 10px), min(10px, 100%), max(40px, 4em));
}

a {
width: clamp(10%, 2px, 4rem);
}

a {
width: clamp(10%, 2px, 4rem);
height: calc(10px + 100%);
}

a {
width: clamp(10%, 2.5px, 5.1px);
}

a {
width: clamp(10%, 2.5px, 5px);
}

a {
width: clamp(calc(10px + 100%), calc(10rem + 200%), 10px);
}

a {
width: clamp(var(--foo-a), var(--foo-b), var(--foo-c));
}

a {
margin: 0 40px 0 calc(-1 * clamp(32px, 16vw, 64px));
}

a {
font-size: clamp(clamp(1rem, 2vw, 3rem), 4vw, 5rem);
}

a {
width: calc(10px + clamp(2px, 4px, 6px));
}
51 changes: 51 additions & 0 deletions crates/swc_css_prefixer/tests/fixture/clamp/output.css
@@ -0,0 +1,51 @@
a {
width: max(10px, min(64px, 80px));
width: clamp(10px, 64px, 80px);
}
a {
width: max(-webkit-calc(100% - 10px), min(min(10px, 100%), max(40px, 4em)));
width: clamp(-moz-calc(100% - 10px), min(10px, 100%), max(40px, 4em));
width: clamp(calc(100% - 10px), min(10px, 100%), max(40px, 4em));
}
a {
width: max(10%, min(2px, 4rem));
width: clamp(10%, 2px, 4rem);
}
a {
width: max(10%, min(2px, 4rem));
width: clamp(10%, 2px, 4rem);
height: -webkit-calc(10px + 100%);
height: -moz-calc(10px + 100%);
height: calc(10px + 100%);
}
a {
width: max(10%, min(2.5px, 5.1px));
width: clamp(10%, 2.5px, 5.1px);
}
a {
width: max(10%, min(2.5px, 5px));
width: clamp(10%, 2.5px, 5px);
}
a {
width: max(-webkit-calc(10px + 100%), min(-webkit-calc(10rem + 200%), 10px));
width: clamp(-moz-calc(10px + 100%), -moz-calc(10rem + 200%), 10px);
width: clamp(calc(10px + 100%), calc(10rem + 200%), 10px);
}
a {
width: max(var(--foo-a), min(var(--foo-b), var(--foo-c)));
width: clamp(var(--foo-a), var(--foo-b), var(--foo-c));
}
a {
margin: 0 40px 0 -webkit-calc(-1 * max(32px, min(16vw, 64px)));
margin: 0 40px 0 -moz-calc(-1 * clamp(32px, 16vw, 64px));
margin: 0 40px 0 calc(-1 * clamp(32px, 16vw, 64px));
}
a {
font-size: max(max(1rem, min(2vw, 3rem)), min(4vw, 5rem));
font-size: clamp(clamp(1rem, 2vw, 3rem), 4vw, 5rem);
}
a {
width: -webkit-calc(10px + max(2px, min(4px, 6px)));
width: -moz-calc(10px + clamp(2px, 4px, 6px));
width: calc(10px + clamp(2px, 4px, 6px));
}
@@ -0,0 +1,34 @@
a {
width: clamp(10px, 64px, 80px);
}
a {
width: clamp(calc(100% - 10px), min(10px, 100%), max(40px, 4em));
}
a {
width: clamp(10%, 2px, 4rem);
}
a {
width: clamp(10%, 2px, 4rem);
height: calc(10px + 100%);
}
a {
width: clamp(10%, 2.5px, 5.1px);
}
a {
width: clamp(10%, 2.5px, 5px);
}
a {
width: clamp(calc(10px + 100%), calc(10rem + 200%), 10px);
}
a {
width: clamp(var(--foo-a), var(--foo-b), var(--foo-c));
}
a {
margin: 0 40px 0 calc(-1 * clamp(32px, 16vw, 64px));
}
a {
font-size: clamp(clamp(1rem, 2vw, 3rem), 4vw, 5rem);
}
a {
width: calc(10px + clamp(2px, 4px, 6px));
}

0 comments on commit 1722428

Please sign in to comment.