mirror of
https://github.com/swc-project/swc.git
synced 2024-10-04 20:28:43 +03:00
feat(css/minifier): Compress hsl colors (#5142)
This commit is contained in:
parent
de484bf98a
commit
714ff5321d
@ -87,12 +87,9 @@ impl VisitMut for CompressAngle {
|
||||
return;
|
||||
}
|
||||
|
||||
let from = match &*angle.unit.value.to_lowercase() {
|
||||
"deg" => AngleType::Deg,
|
||||
"grad" => AngleType::Grad,
|
||||
"rad" => AngleType::Rad,
|
||||
"turn" => AngleType::Turn,
|
||||
_ => return,
|
||||
let from = match get_angle_type(&*angle.unit.value.to_lowercase()) {
|
||||
Some(angel_type) => angel_type,
|
||||
None => return,
|
||||
};
|
||||
|
||||
let deg = to_deg(angle.value.value, from);
|
||||
@ -117,14 +114,14 @@ impl VisitMut for CompressAngle {
|
||||
}
|
||||
}
|
||||
|
||||
enum AngleType {
|
||||
pub(crate) enum AngleType {
|
||||
Deg,
|
||||
Grad,
|
||||
Rad,
|
||||
Turn,
|
||||
}
|
||||
|
||||
fn to_deg(value: f64, from: AngleType) -> f64 {
|
||||
pub(crate) fn to_deg(value: f64, from: AngleType) -> f64 {
|
||||
match from {
|
||||
AngleType::Deg => value,
|
||||
AngleType::Grad => value * 180.0 / 200.0,
|
||||
@ -133,6 +130,16 @@ fn to_deg(value: f64, from: AngleType) -> f64 {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_angle_type(unit: &str) -> Option<AngleType> {
|
||||
match unit {
|
||||
"deg" => Some(AngleType::Deg),
|
||||
"grad" => Some(AngleType::Grad),
|
||||
"rad" => Some(AngleType::Rad),
|
||||
"turn" => Some(AngleType::Turn),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn normalize_deg(mut value: f64) -> f64 {
|
||||
value = (value % 360.0 + 360.0) % 360.0;
|
||||
|
||||
|
@ -3,6 +3,8 @@ use swc_css_ast::*;
|
||||
use swc_css_utils::NAMED_COLORS;
|
||||
use swc_css_visit::{VisitMut, VisitMutWith};
|
||||
|
||||
use crate::compress::angle::{get_angle_type, to_deg};
|
||||
|
||||
fn get_short_hex(v: u32) -> u32 {
|
||||
((v & 0x0ff00000) >> 12) | ((v & 0x00000ff0) >> 4)
|
||||
}
|
||||
@ -55,7 +57,63 @@ fn get_named_color_by_hex(v: u32) -> Option<&'static str> {
|
||||
Some(s)
|
||||
}
|
||||
|
||||
macro_rules! make_color_from_rgb {
|
||||
static ONE_THIRD: f64 = 1.0 / 3.0;
|
||||
static ONE_SECOND: f64 = 1.0 / 2.0;
|
||||
static ONE_SIX: f64 = 1.0 / 6.0;
|
||||
static TWO_THIRD: f64 = 2.0 / 3.0;
|
||||
|
||||
fn hsl_to_rgb(hsl: [f64; 3]) -> [f64; 3] {
|
||||
let [h, s, l] = hsl;
|
||||
|
||||
let r;
|
||||
let g;
|
||||
let b;
|
||||
|
||||
if s == 0.0 {
|
||||
r = l;
|
||||
g = l;
|
||||
b = l;
|
||||
} else {
|
||||
let hue2rgb = |p: f64, q: f64, mut t: f64| -> f64 {
|
||||
if t < 0.0 {
|
||||
t += 1.0;
|
||||
}
|
||||
|
||||
if t > 1.0 {
|
||||
t -= 1.0;
|
||||
}
|
||||
|
||||
if t < ONE_SIX {
|
||||
return p + (q - p) * 6.0 * t;
|
||||
}
|
||||
|
||||
if t < ONE_SECOND {
|
||||
return q;
|
||||
}
|
||||
|
||||
if t < TWO_THIRD {
|
||||
return p + (q - p) * (TWO_THIRD - t) * 6.0;
|
||||
}
|
||||
|
||||
p
|
||||
};
|
||||
|
||||
let q = if l < 0.5 {
|
||||
l * (1.0 + s)
|
||||
} else {
|
||||
l + s - l * s
|
||||
};
|
||||
let p = 2.0 * l - q;
|
||||
|
||||
r = hue2rgb(p, q, h + ONE_THIRD);
|
||||
g = hue2rgb(p, q, h);
|
||||
b = hue2rgb(p, q, h - ONE_THIRD);
|
||||
}
|
||||
|
||||
[r * 255.0, g * 255.0, b * 255.0]
|
||||
}
|
||||
|
||||
macro_rules! make_color {
|
||||
($span:expr,$r:expr,$g:expr,$b:expr) => {{
|
||||
let hex: u32 = (($r as u32) << 16) | (($g as u32) << 8) | ($b as u32);
|
||||
|
||||
@ -82,7 +140,7 @@ macro_rules! make_color_from_rgb {
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! make_color_from_rgba {
|
||||
macro_rules! make_color_with_alpha {
|
||||
($span:expr,$r:expr,$g:expr,$b:expr,$a:expr,$t:expr) => {{
|
||||
// TODO improve when we will have browserslist
|
||||
let is_alpha_hex_supported = false;
|
||||
@ -232,12 +290,11 @@ impl VisitMut for CompressColor {
|
||||
..
|
||||
})) => match &*value.to_lowercase() {
|
||||
"transparent" => {
|
||||
*color = make_color_from_rgba!(*span, 0.0, 0.0, 0.0, 0.0, true);
|
||||
*color = make_color_with_alpha!(*span, 0.0, 0.0, 0.0, 0.0, true);
|
||||
}
|
||||
name => {
|
||||
if let Some(value) = NAMED_COLORS.get(name) {
|
||||
*color =
|
||||
make_color_from_rgb!(*span, value.rgb[0], value.rgb[1], value.rgb[2])
|
||||
*color = make_color!(*span, value.rgb[0], value.rgb[1], value.rgb[2])
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -316,14 +373,109 @@ impl VisitMut for CompressColor {
|
||||
_ => return,
|
||||
};
|
||||
|
||||
match (r, g, b, a) {
|
||||
(Some(r), Some(g), Some(b), None) => {
|
||||
*color = make_color_from_rgb!(*span, r, g, b);
|
||||
if let (Some(r), Some(g), Some(b), a) = (r, g, b, a) {
|
||||
if let Some(a) = a {
|
||||
*color = make_color_with_alpha!(*span, r, g, b, a.0, a.1);
|
||||
} else {
|
||||
*color = make_color!(*span, r, g, b);
|
||||
}
|
||||
(Some(r), Some(g), Some(b), Some(a)) => {
|
||||
*color = make_color_from_rgba!(*span, r, g, b, a.0, a.1);
|
||||
}
|
||||
}
|
||||
Color::AbsoluteColorBase(AbsoluteColorBase::Function(Function {
|
||||
span,
|
||||
name,
|
||||
value,
|
||||
..
|
||||
})) if matches!(&*name.value, "hsl" | "hsla") => {
|
||||
let hsla: Vec<_> = value
|
||||
.iter()
|
||||
.filter(|n| {
|
||||
!matches!(
|
||||
n,
|
||||
ComponentValue::Delimiter(Delimiter {
|
||||
value: DelimiterValue::Comma | DelimiterValue::Solidus,
|
||||
..
|
||||
})
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let h = match hsla.get(0) {
|
||||
Some(ComponentValue::Hue(hue)) => {
|
||||
let mut value = match hue {
|
||||
Hue::Number(Number { value, .. }) => *value,
|
||||
Hue::Angle(Angle {
|
||||
value: Number { value, .. },
|
||||
unit: Ident { value: unit, .. },
|
||||
..
|
||||
}) => {
|
||||
let angel_type = match get_angle_type(&unit.to_lowercase()) {
|
||||
Some(angel_type) => angel_type,
|
||||
_ => return,
|
||||
};
|
||||
|
||||
to_deg(*value, angel_type)
|
||||
}
|
||||
};
|
||||
|
||||
value %= 360.0;
|
||||
|
||||
if value < 0.0 {
|
||||
value += 360.0;
|
||||
}
|
||||
|
||||
Some(value / 360.0)
|
||||
}
|
||||
_ => return,
|
||||
};
|
||||
let s = match hsla.get(1) {
|
||||
Some(ComponentValue::Percentage(Percentage {
|
||||
value: Number { value, .. },
|
||||
..
|
||||
})) => Some(*value / 100.0),
|
||||
_ => return,
|
||||
};
|
||||
let l = match hsla.get(2) {
|
||||
Some(ComponentValue::Percentage(Percentage {
|
||||
value: Number { value, .. },
|
||||
..
|
||||
})) => Some(*value / 100.0),
|
||||
_ => return,
|
||||
};
|
||||
let a = match hsla.get(3) {
|
||||
Some(ComponentValue::AlphaValue(AlphaValue::Number(number))) => {
|
||||
if number.value == 1.0 {
|
||||
None
|
||||
} else {
|
||||
Some((number.value, true))
|
||||
}
|
||||
}
|
||||
Some(ComponentValue::AlphaValue(AlphaValue::Percentage(percentage))) => {
|
||||
if percentage.value.value == 100.0 {
|
||||
None
|
||||
} else {
|
||||
Some((percentage.value.value / 100.0, false))
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
_ => return,
|
||||
};
|
||||
|
||||
if let (Some(h), Some(s), Some(l), a) = (h, s, l, a) {
|
||||
let rgb = hsl_to_rgb([h, s, l]);
|
||||
|
||||
if let Some(a) = a {
|
||||
*color = make_color_with_alpha!(
|
||||
*span,
|
||||
rgb[0].round(),
|
||||
rgb[1].round(),
|
||||
rgb[2].round(),
|
||||
a.0,
|
||||
a.1
|
||||
);
|
||||
} else {
|
||||
*color = make_color!(*span, rgb[0].round(), rgb[1].round(), rgb[2].round());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
@ -122,54 +122,62 @@
|
||||
color: rgb(from #FF0000 255 255 255);
|
||||
}
|
||||
|
||||
.color-31 {
|
||||
color: rgb(from red 255 255 255);
|
||||
}
|
||||
.class-31 {
|
||||
color: hsl(362deg, 100%, 50%);
|
||||
color: hsl(360, 0%, 50%);
|
||||
color: hsl(360, 100%, 0%);
|
||||
|
||||
.color-32 {
|
||||
color: rgb(from #f00 255 255 255);
|
||||
}
|
||||
color: hsl(90deg, 100%, 50%);
|
||||
color: hsl(90grad, 100%, 50%);
|
||||
color: hsl(1.0708rad, 100%, 50%);
|
||||
color: hsl(0.25turn, 100%, 50%);
|
||||
|
||||
.color-33 {
|
||||
color: rgb(from yellow 255 255 255);
|
||||
}
|
||||
color: hsl(0deg, 100%, 50%);
|
||||
color: hsl(360deg, 100%, 50%);
|
||||
color: hsl(720deg, 100%, 50%);
|
||||
color: hsl(161deg, 100%, 50%);
|
||||
|
||||
.color-34 {
|
||||
color: rgb(from snow 255 255 255);
|
||||
}
|
||||
color: hsl(360, 100%, 50%);
|
||||
color: hsl(315, 100%, 50%);
|
||||
color: hsl(270, 100%, 50%);
|
||||
color: hsl(225, 100%, 50%);
|
||||
color: hsl(180, 100%, 50%);
|
||||
color: hsl(135, 100%, 50%);
|
||||
color: hsl(90, 100%, 50%);
|
||||
color: hsl(45, 100%, 50%);
|
||||
color: hsl(0, 100%, 50%);
|
||||
|
||||
.color-35 {
|
||||
color: rgb(from #D2B48C 255 255 255);
|
||||
}
|
||||
color: hsl(360, 100%, 50%, 1.0);
|
||||
color: hsl(315, 100%, 50%, 100%);
|
||||
color: hsl(270, 100%, 50%, 0.5);
|
||||
color: hsl(225, 100%, 50%, 0.5);
|
||||
color: hsl(180, 100%, 50%, 0.5);
|
||||
color: hsl(135, 100%, 50%, 0.5);
|
||||
color: hsl(90, 100%, 50%, 0.5);
|
||||
color: hsl(45, 100%, 50%, 0.5);
|
||||
color: hsl(0, 100%, 50%, 0.5);
|
||||
|
||||
.color-36 {
|
||||
color: rgb(from #ff0000 255 255 255);
|
||||
}
|
||||
color: hsla(360, 100%, 50%);
|
||||
color: hsla(315, 100%, 50%);
|
||||
color: hsla(270, 100%, 50%);
|
||||
color: hsla(225, 100%, 50%);
|
||||
color: hsla(180, 100%, 50%);
|
||||
color: hsla(135, 100%, 50%);
|
||||
color: hsla(90, 100%, 50%);
|
||||
color: hsla(45, 100%, 50%);
|
||||
color: hsla(0, 100%, 50%);
|
||||
|
||||
.color-37 {
|
||||
color: rgb(from white 255 255 255);
|
||||
}
|
||||
color: hsla(360, 100%, 50%, 1.0);
|
||||
color: hsla(315, 100%, 50%, 100%);
|
||||
color: hsla(270, 100%, 50%, 0.5);
|
||||
color: hsla(225, 100%, 50%, 0.5);
|
||||
color: hsla(180, 100%, 50%, 0.5);
|
||||
color: hsla(135, 100%, 50%, 0.5);
|
||||
color: hsla(90, 100%, 50%, 0.5);
|
||||
color: hsla(45, 100%, 50%, 0.5);
|
||||
color: hsla(0, 100%, 50%, 0.5);
|
||||
|
||||
.color-38 {
|
||||
color: rgb(from #ffffff 255 255 255);
|
||||
}
|
||||
|
||||
.color-39 {
|
||||
color: rgb(from #fff 255 255 255);
|
||||
}
|
||||
|
||||
.color-40 {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.color-41 {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.color-42 {
|
||||
color: #ffffffff;
|
||||
}
|
||||
|
||||
.color-43 {
|
||||
color: #ffff;
|
||||
}
|
||||
color: hsl(361, 100%, 50%);
|
||||
color: hsl(362, 100%, 50%);
|
||||
color: hsl(363, 100%, 50%);
|
||||
}
|
@ -1 +1 @@
|
||||
.color{color:rgb(from rgba(0,0,0,0)255 255 255)}.color-1{color:rgb(from red 255 255 255)}.color-2{color:rgb(from red 255 255 255)}.color-3{color:rgb(from#f00 255 255 255)}.color-4{color:rgb(from#eee8aa 255 255 255)}.color-5{color:rgb(from#ff0 255 255 255)}.color-6{color:rgb(from snow 255 255 255)}.color-7{color:rgba(123,123,123,0)}.color-8{color:#7b7b7b}.color-9{color:#7b7b7b}.color-10{color:#7b7b7b}.color-11{color:#7b7b7b}.color-12{color:rgba(51,102,77,23%)}.color-13{color:#7b7b7b}.color-14{color:#6496c8}.class-15{color:#7b7b7b}.class-16{color:rgba(123,123,123,99%)}.class-17{color:#7b7b7b}.class-18{color:rgba(179,82,31,13%)}.class-19{color:rgba(180,82,31,13%)}.class-20{color:rgba(181,82,31,13%)}.class-21{color:rgba(182,82,31,13%)}.class-22{color:rgba(184,82,31,13%)}.class-23{color:rgba(181.4,181,181,13%)}.class-24{color:rgba(181.5,181,181,13%)}.class-25{color:rgba(181,181,181,.1%)}.class-26{color:rgba(181,181,181,.4%)}.color-27{color:rgb(from#eee8aa 255 255 255)}.color-28{color:rgb(from teal 255 255 255)}.color-29{color:rgb(from red 255 255 255)}.color-30{color:rgb(from red 255 255 255)}.color-31{color:rgb(from red 255 255 255)}.color-32{color:rgb(from#f00 255 255 255)}.color-33{color:rgb(from#ff0 255 255 255)}.color-34{color:rgb(from snow 255 255 255)}.color-35{color:rgb(from tan 255 255 255)}.color-36{color:rgb(from red 255 255 255)}.color-37{color:rgb(from#fff 255 255 255)}.color-38{color:rgb(from#fff 255 255 255)}.color-39{color:rgb(from#fff 255 255 255)}.color-40{color:#fff}.color-41{color:#fff}.color-42{color:#fff}.color-43{color:#ffff}
|
||||
.color{color:rgb(from rgba(0,0,0,0)255 255 255)}.color-1{color:rgb(from red 255 255 255)}.color-2{color:rgb(from red 255 255 255)}.color-3{color:rgb(from#f00 255 255 255)}.color-4{color:rgb(from#eee8aa 255 255 255)}.color-5{color:rgb(from#ff0 255 255 255)}.color-6{color:rgb(from snow 255 255 255)}.color-7{color:rgba(123,123,123,0)}.color-8{color:#7b7b7b}.color-9{color:#7b7b7b}.color-10{color:#7b7b7b}.color-11{color:#7b7b7b}.color-12{color:rgba(51,102,77,23%)}.color-13{color:#7b7b7b}.color-14{color:#6496c8}.class-15{color:#7b7b7b}.class-16{color:rgba(123,123,123,99%)}.class-17{color:#7b7b7b}.class-18{color:rgba(179,82,31,13%)}.class-19{color:rgba(180,82,31,13%)}.class-20{color:rgba(181,82,31,13%)}.class-21{color:rgba(182,82,31,13%)}.class-22{color:rgba(184,82,31,13%)}.class-23{color:rgba(181.4,181,181,13%)}.class-24{color:rgba(181.5,181,181,13%)}.class-25{color:rgba(181,181,181,.1%)}.class-26{color:rgba(181,181,181,.4%)}.color-27{color:rgb(from#eee8aa 255 255 255)}.color-28{color:rgb(from teal 255 255 255)}.color-29{color:rgb(from red 255 255 255)}.color-30{color:rgb(from red 255 255 255)}.class-31{color:#ff0900;color:gray;color:#000;color:#80ff00;color:#a6ff00;color:#f9ff00;color:#80ff00;color:red;color:red;color:red;color:#00ffae;color:red;color:#ff00bf;color:#7f00ff;color:#0040ff;color:#0ff;color:#00ff40;color:#80ff00;color:#ffbf00;color:red;color:red;color:#ff00bf;color:rgba(127,0,255,.5);color:rgba(0,64,255,.5);color:rgba(0,255,255,.5);color:rgba(0,255,64,.5);color:rgba(128,255,0,.5);color:rgba(255,191,0,.5);color:rgba(255,0,0,.5);color:red;color:#ff00bf;color:#7f00ff;color:#0040ff;color:#0ff;color:#00ff40;color:#80ff00;color:#ffbf00;color:red;color:red;color:#ff00bf;color:rgba(127,0,255,.5);color:rgba(0,64,255,.5);color:rgba(0,255,255,.5);color:rgba(0,255,64,.5);color:rgba(128,255,0,.5);color:rgba(255,191,0,.5);color:rgba(255,0,0,.5);color:#ff0400;color:#ff0900;color:#ff0d00}
|
||||
|
Loading…
Reference in New Issue
Block a user