feat(css/codegen): Implement minification of identifiers (#3466)

This commit is contained in:
Alexander Akait 2022-02-07 17:29:38 +03:00 committed by GitHub
parent 1234fac4d5
commit 81850c2b30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 169 additions and 52 deletions

View File

@ -709,11 +709,12 @@ where
fn emit_list_values(&mut self, nodes: &[Value], format: ListFormat) -> Result { fn emit_list_values(&mut self, nodes: &[Value], format: ListFormat) -> Result {
let iter = nodes.iter(); let iter = nodes.iter();
let len = nodes.len();
for (idx, node) in iter.enumerate() { for (idx, node) in iter.enumerate() {
emit!(self, node); emit!(self, node);
if idx != nodes.len() - 1 { if idx != len - 1 {
let need_delim = match node { let need_delim = match node {
Value::SimpleBlock(_) Value::SimpleBlock(_)
| Value::Function(_) | Value::Function(_)
@ -727,6 +728,31 @@ where
})) => false, })) => false,
_ => !self.config.minify, _ => !self.config.minify,
}, },
Value::Ident(_) => match nodes.get(idx + 1) {
Some(Value::SimpleBlock(_))
| Some(Value::Color(Color::HexColor(_)))
| Some(Value::Str(_)) => !self.config.minify,
Some(Value::Delimiter(_)) => false,
Some(Value::Number(n)) => {
if self.config.minify {
let minified = minify_numeric(n.value);
!minified.starts_with('.')
} else {
true
}
}
Some(Value::Dimension(n)) => {
if self.config.minify {
let minified = minify_numeric(n.value.value);
!minified.starts_with('.')
} else {
true
}
}
_ => true,
},
_ => match nodes.get(idx + 1) { _ => match nodes.get(idx + 1) {
Some(Value::SimpleBlock(_)) | Some(Value::Color(Color::HexColor(_))) => { Some(Value::SimpleBlock(_)) | Some(Value::Color(Color::HexColor(_))) => {
!self.config.minify !self.config.minify
@ -968,52 +994,9 @@ where
#[emitter] #[emitter]
fn emit_number(&mut self, n: &Number) -> Result { fn emit_number(&mut self, n: &Number) -> Result {
if self.config.minify { if self.config.minify {
if n.value.is_sign_negative() && n.value == 0.0 { let minified = minify_numeric(n.value);
self.wr.write_raw(Some(n.span), "-0")?;
} else {
let mut minified = n.value.to_string();
if minified.starts_with("0.") {
minified.replace_range(0..1, "");
} else if minified.starts_with("-0.") {
minified.replace_range(1..2, "");
}
if minified.starts_with(".000") {
let mut cnt = 3;
for &v in minified.as_bytes().iter().skip(4) {
if v == b'0' {
cnt += 1;
} else {
break;
}
}
minified.replace_range(0..cnt + 1, "");
let remain_len = minified.len();
minified.push_str("e-");
minified.push_str(&(remain_len + cnt).to_string());
} else if minified.ends_with("000") {
let mut cnt = 3;
for &v in minified.as_bytes().iter().rev().skip(3) {
if v == b'0' {
cnt += 1;
} else {
break;
}
}
minified.truncate(minified.len() - cnt);
minified.push('e');
minified.push_str(&cnt.to_string());
}
self.wr.write_raw(Some(n.span), &minified)?; self.wr.write_raw(Some(n.span), &minified)?;
}
} else { } else {
self.wr.write_raw(Some(n.span), &n.raw)?; self.wr.write_raw(Some(n.span), &n.raw)?;
} }
@ -1502,6 +1485,54 @@ where
} }
} }
fn minify_numeric(value: f64) -> String {
if value.is_sign_negative() && value == 0.0 {
return "-0".to_owned();
}
let mut minified = value.to_string();
if minified.starts_with("0.") {
minified.replace_range(0..1, "");
} else if minified.starts_with("-0.") {
minified.replace_range(1..2, "");
}
if minified.starts_with(".000") {
let mut cnt = 3;
for &v in minified.as_bytes().iter().skip(4) {
if v == b'0' {
cnt += 1;
} else {
break;
}
}
minified.replace_range(0..cnt + 1, "");
let remain_len = minified.len();
minified.push_str("e-");
minified.push_str(&(remain_len + cnt).to_string());
} else if minified.ends_with("000") {
let mut cnt = 3;
for &v in minified.as_bytes().iter().rev().skip(3) {
if v == b'0' {
cnt += 1;
} else {
break;
}
}
minified.truncate(minified.len() - cnt);
minified.push('e');
minified.push_str(&cnt.to_string());
}
minified
}
fn minify_hex_color(value: &str) -> String { fn minify_hex_color(value: &str) -> String {
let length = value.len(); let length = value.len();

View File

@ -99,3 +99,48 @@ div {
property: 100.1e-6; property: 100.1e-6;
property: 10001000000; property: 10001000000;
} }
div {
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out
}
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
grid-auto-rows: minmax(100px, auto);
}
.one {
grid-column: 1 / 3;
grid-row: 1;
}
.two {
grid-column: 2 / 4;
grid-row: 1 / 3;
}
.three {
grid-column: 1;
grid-row: 2 / 5;
}
.four {
grid-column: 3;
grid-row: 3;
}
.five {
grid-column: 2;
grid-row: 4;
}
.six {
grid-column: 3;
grid-row: 4;
}
#grid {
display: grid;
height: 100px;
grid-template: repeat(4, 1fr) / 50px 100px;
}
.foo {
grid-area: 2 span / another-grid-area span;
}

View File

@ -94,3 +94,24 @@ property: -000000;
property: 100.1e-5; property: 100.1e-5;
property: 100.1e-6; property: 100.1e-6;
property: 10001000000} property: 10001000000}
div {transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out}
.wrapper {display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
grid-auto-rows: minmax(100px, auto)}
.one {grid-column: 1/ 3;
grid-row: 1}
.two {grid-column: 2/ 4;
grid-row: 1/ 3}
.three {grid-column: 1;
grid-row: 2/ 5}
.four {grid-column: 3;
grid-row: 3}
.five {grid-column: 2;
grid-row: 4}
.six {grid-column: 3;
grid-row: 4}
#grid {display: grid;
height: 100px;
grid-template: repeat(4, 1fr) / 50px 100px}
.foo {grid-area: 2 span/ another-grid-area span}

View File

@ -1 +1 @@
div{line-height:100;margin:20 30;margin:20 30px;margin:20px 30}div{property:10;property:10;property:-10;property:.1;property:.1;property:-.1;property:-.1;property:.1;property:0;property:10;property:.1;property:12.34;property:.1;property:1;property:0;property:0;property:-0;property:0;property:1.2;property:120;property:100;property:20;property:120;property:120;property:.012;property:-1;property:-1.2;property:.2;property:-.2;property:.2;property:-1200;property:1.75;property:1.75;property:1;property:10;property:10;property:.1;property:1e-10;property:1 2;property:1 -2;property:4.01;property:-456.8;property:.6;property:.006;property:1e4;property:-.034;property:.56;property:1e7;property:1e7;property:0;property:-0;property:0;property:0;property:1;property:10;property:100;property:1e3;property:1e4;property:1e5;property:1;property:.1;property:.01;property:.001;property:1e-4;property:1e-5;property:-1;property:-.1;property:-.01;property:-.001;property:-.0001;property:-.00001;property:.1;property:.01;property:.001;property:1e-4;property:1e-5;property:1e-6;property:.5;property:.05;property:.005;property:5e-4;property:5e-5;property:5e-6;property:15e-6;property:1543e-8;property:1543e-8;property:0;property:0;property:-0;property:.001001;property:1001e-7;property:10001e6} div{line-height:100;margin:20 30;margin:20 30px;margin:20px 30}div{property:10;property:10;property:-10;property:.1;property:.1;property:-.1;property:-.1;property:.1;property:0;property:10;property:.1;property:12.34;property:.1;property:1;property:0;property:0;property:-0;property:0;property:1.2;property:120;property:100;property:20;property:120;property:120;property:.012;property:-1;property:-1.2;property:.2;property:-.2;property:.2;property:-1200;property:1.75;property:1.75;property:1;property:10;property:10;property:.1;property:1e-10;property:1 2;property:1 -2;property:4.01;property:-456.8;property:.6;property:.006;property:1e4;property:-.034;property:.56;property:1e7;property:1e7;property:0;property:-0;property:0;property:0;property:1;property:10;property:100;property:1e3;property:1e4;property:1e5;property:1;property:.1;property:.01;property:.001;property:1e-4;property:1e-5;property:-1;property:-.1;property:-.01;property:-.001;property:-.0001;property:-.00001;property:.1;property:.01;property:.001;property:1e-4;property:1e-5;property:1e-6;property:.5;property:.05;property:.005;property:5e-4;property:5e-5;property:5e-6;property:15e-6;property:1543e-8;property:1543e-8;property:0;property:0;property:-0;property:.001001;property:1001e-7;property:10001e6}div{transition:border-color.15s ease-in-out,box-shadow.15s ease-in-out}.wrapper{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;grid-auto-rows:minmax(100px,auto)}.one{grid-column:1/3;grid-row:1}.two{grid-column:2/4;grid-row:1/3}.three{grid-column:1;grid-row:2/5}.four{grid-column:3;grid-row:3}.five{grid-column:2;grid-row:4}.six{grid-column:3;grid-row:4}#grid{display:grid;height:100px;grid-template:repeat(4,1fr)/50px 100px}.foo{grid-area:2 span/another-grid-area span}

View File

@ -48,3 +48,20 @@ div {
background: url("http://example.com/foo\'bar.jpg"); background: url("http://example.com/foo\'bar.jpg");
background: url("http://example.com/foo\"bar.jpg"); background: url("http://example.com/foo\"bar.jpg");
} }
div {
grid-template: [header-top] "a a a" [header-bottom]
[main-top] "b b b" 1fr [main-bottom]
/ auto 1fr auto;
}
.other {
grid-template: [header-left] "head head" 30px [header-right]
[main-left] "nav main" 1fr [main-right]
[footer-left] "nav foot" 30px [footer-right]
/ 120px 1fr;
}
.prop {
prop: name "test";
}

View File

@ -36,3 +36,6 @@ background: url('http://example.com/foo\'bar.jpg');
background: url('http://example.com/foo\"bar.jpg'); background: url('http://example.com/foo\"bar.jpg');
background: url("http://example.com/foo\'bar.jpg"); background: url("http://example.com/foo\'bar.jpg");
background: url("http://example.com/foo\"bar.jpg")} background: url("http://example.com/foo\"bar.jpg")}
div {grid-template: [header-top] "a a a" [header-bottom] [main-top] "b b b" 1fr [main-bottom] / auto 1fr auto}
.other {grid-template: [header-left] "head head" 30px [header-right] [main-left] "nav main" 1fr [main-right] [footer-left] "nav foot" 30px [footer-right] / 120px 1fr}
.prop {prop: name "test"}

View File

@ -1 +1 @@
div{content:"⬇️";content:"😀";content:"'test'";content:"\\'test'";content:"\\\\'test'";content:'"string" is string';content:"'string' is string";content:'"string" is string';content:"'string' is string";content:'"string" is string';content:"'string' is string";content:"'string' is \"string\"";content:"'string' is \"string\"";content:"'test' 'test'";content:'"test" "test"';content:"'test'";content:"'test'";content:'"test"';content:"'test'";content:"'test'";content:'"test"';content:'"string"';content:"'string'";content:"This string has a \a line break in it.";content:"This string has a \a line break in it.";content:"This string has a \a line break in it.";content:"This string has a \a line break in it.";content:'"test" "test" "test" \'test\'';content:'"test" "test" "test" \'test\'';content:"'test' 'test' 'test' \"test\"";content:'"test" "test" "test" \'test\'';content:"'test' 'test' 'test' \"test\"";content:"'test' 'test' 'test' \"test\"";content:"\\'test\\' \\'test\\' \\'test\\' \\\"test\\\"";background:url("http://example.com/foo'bar.jpg");background:url('http://example.com/foo"bar.jpg');background:url("http://example.com/foo'bar.jpg");background:url('http://example.com/foo"bar.jpg')} div{content:"⬇️";content:"😀";content:"'test'";content:"\\'test'";content:"\\\\'test'";content:'"string" is string';content:"'string' is string";content:'"string" is string';content:"'string' is string";content:'"string" is string';content:"'string' is string";content:"'string' is \"string\"";content:"'string' is \"string\"";content:"'test' 'test'";content:'"test" "test"';content:"'test'";content:"'test'";content:'"test"';content:"'test'";content:"'test'";content:'"test"';content:'"string"';content:"'string'";content:"This string has a \a line break in it.";content:"This string has a \a line break in it.";content:"This string has a \a line break in it.";content:"This string has a \a line break in it.";content:'"test" "test" "test" \'test\'';content:'"test" "test" "test" \'test\'';content:"'test' 'test' 'test' \"test\"";content:'"test" "test" "test" \'test\'';content:"'test' 'test' 'test' \"test\"";content:"'test' 'test' 'test' \"test\"";content:"\\'test\\' \\'test\\' \\'test\\' \\\"test\\\"";background:url("http://example.com/foo'bar.jpg");background:url('http://example.com/foo"bar.jpg');background:url("http://example.com/foo'bar.jpg");background:url('http://example.com/foo"bar.jpg')}div{grid-template:[header-top]"a a a"[header-bottom][main-top]"b b b"1fr[main-bottom]/auto 1fr auto}.other{grid-template:[header-left]"head head"30px[header-right][main-left]"nav main"1fr[main-right][footer-left]"nav foot"30px[footer-right]/120px 1fr}.prop{prop:name"test"}