From 899fbd693af2b1cfc784ca1b5100dc60ea7f7d00 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Fri, 15 Aug 2025 09:52:38 +0800 Subject: [PATCH] chore: Use `html5minify` instead of minify-html. (#1137) Ref #1132 This change to reduce release mode binary size from 21MB to 12MB. ## HTML Render example image --- Cargo.lock | 103 ++++++++++++++++++++++++++++++------- crates/ui/Cargo.toml | 3 +- crates/ui/src/text/html.rs | 26 +++++++--- 3 files changed, 104 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 82bbe1f5..2c5f3380 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1494,7 +1494,7 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" dependencies = [ - "time", + "time 0.3.41", "version_check", ] @@ -3150,12 +3150,13 @@ dependencies = [ "gpui", "gpui-component-macros", "html5ever 0.27.0", + "html5minify", "image", "indexset", "indoc", "itertools 0.13.0", "markdown", - "markup5ever_rcdom", + "markup5ever_rcdom 0.3.0", "num-traits", "once_cell", "paste", @@ -3167,7 +3168,6 @@ dependencies = [ "serde", "serde_json", "serde_repr", - "simple-minify-html", "smallvec", "smol 1.3.0", "tracing", @@ -3437,6 +3437,20 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "html5ever" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5c13fb08e5d4dfc151ee5e88bae63f7773d61852f3bdc73c9f4b9e1bde03148" +dependencies = [ + "log", + "mac", + "markup5ever 0.10.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "html5ever" version = "0.26.0" @@ -3465,6 +3479,16 @@ dependencies = [ "syn 2.0.105", ] +[[package]] +name = "html5minify" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f0717993787d29fc1177a9a5233f7979517fdaa8eb498fb45ae36ffe6c65a17" +dependencies = [ + "html5ever 0.25.2", + "markup5ever_rcdom 0.1.0", +] + [[package]] name = "http" version = "1.3.1" @@ -4358,6 +4382,20 @@ dependencies = [ "unicode-id", ] +[[package]] +name = "markup5ever" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a24f40fb03852d1cdd84330cddcaf98e9ec08a7b7768e952fad3b4cf048ec8fd" +dependencies = [ + "log", + "phf 0.8.0", + "phf_codegen 0.8.0", + "string_cache", + "string_cache_codegen", + "tendril", +] + [[package]] name = "markup5ever" version = "0.11.0" @@ -4386,6 +4424,18 @@ dependencies = [ "tendril", ] +[[package]] +name = "markup5ever_rcdom" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f015da43bcd8d4f144559a3423f4591d69b8ce0652c905374da7205df336ae2b" +dependencies = [ + "html5ever 0.25.2", + "markup5ever 0.10.1", + "tendril", + "xml5ever 0.16.2", +] + [[package]] name = "markup5ever_rcdom" version = "0.3.0" @@ -4395,7 +4445,7 @@ dependencies = [ "html5ever 0.27.0", "markup5ever 0.12.1", "tendril", - "xml5ever", + "xml5ever 0.18.1", ] [[package]] @@ -5651,7 +5701,7 @@ dependencies = [ "indexmap 2.10.0", "quick-xml 0.38.1", "serde", - "time", + "time 0.3.41", ] [[package]] @@ -7249,20 +7299,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" -[[package]] -name = "simple-minify-html" -version = "0.17.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2e14af458c754ee7a0fc21fbb93b824101e2c13a6bd5dc94a32c156a773e36" -dependencies = [ - "aho-corasick", - "itertools 0.14.0", - "memchr", - "rustc-hash 2.1.1", - "serde", - "serde_json", -] - [[package]] name = "simplecss" version = "0.2.2" @@ -7998,6 +8034,17 @@ dependencies = [ "weezl", ] +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi", +] + [[package]] name = "time" version = "0.3.41" @@ -9100,6 +9147,12 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -10414,6 +10467,18 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" +[[package]] +name = "xml5ever" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9234163818fd8e2418fcde330655e757900d4236acd8cc70fef345ef91f6d865" +dependencies = [ + "log", + "mac", + "markup5ever 0.10.1", + "time 0.1.45", +] + [[package]] name = "xml5ever" version = "0.18.1" diff --git a/crates/ui/Cargo.toml b/crates/ui/Cargo.toml index f138939d..bf06bb2e 100644 --- a/crates/ui/Cargo.toml +++ b/crates/ui/Cargo.toml @@ -87,7 +87,8 @@ markdown = "1.0.0" # HTML Parser html5ever = "0.27" markup5ever_rcdom = "0.3.0" -simple-minify-html = "0.17.2" +# For minifying HTML +html5minify = "0.3" # Calendar chrono = "0.4.38" diff --git a/crates/ui/src/text/html.rs b/crates/ui/src/text/html.rs index c2506ee1..fec848d3 100644 --- a/crates/ui/src/text/html.rs +++ b/crates/ui/src/text/html.rs @@ -13,6 +13,7 @@ use gpui::{ use html5ever::tendril::TendrilSink; use html5ever::{local_name, parse_document, LocalName, ParseOpts}; use markup5ever_rcdom::{Node, NodeData, RcDom}; +use regex::bytes::Regex; use crate::v_flex; @@ -82,12 +83,21 @@ pub(super) fn parse_html(source: &str) -> Result { Ok(node) } +// TODO: Find a better and light-weight HTML minifier fn cleanup_html(source: &str) -> Vec { - let cfg = simple_minify_html::Cfg { - keep_closing_tags: true, - ..Default::default() - }; - simple_minify_html::minify(&source.as_bytes(), Some(cfg)).to_vec() + // Replace all \n to space + let re = Regex::new(r"\s*(<.+?>)\s*").unwrap(); + let source: Vec = re.replace_all(source.as_bytes(), b" $1 ").into(); + + let mut w = std::io::Cursor::new(vec![]); + let mut r = std::io::Cursor::new(source.clone()); + let mut minify = html5minify::Minifier::new(&mut w); + minify.omit_doctype(true); + if let Ok(()) = minify.minify(&mut r) { + w.into_inner() + } else { + source + } } #[derive(Clone)] @@ -783,7 +793,7 @@ mod tests { let cleaned = super::cleanup_html(html); assert_eq!( String::from_utf8(cleaned).unwrap(), - "

and code text

" + "

and code text" ); let html = r#"

@@ -794,7 +804,7 @@ mod tests { let cleaned = super::cleanup_html(html); assert_eq!( String::from_utf8(cleaned).unwrap(), - "

and code italic text

" + "

and code italic text" ); } @@ -830,7 +840,7 @@ mod tests { assert_eq!( node.to_markdown(), indoc::indoc! {r#" - and * code italic * text + and *code italic* text ![Example](https://example.com/image.png "Example Image")