diff --git a/Cargo.lock b/Cargo.lock index 7c72f4b9..8cfa6107 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,6 +29,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "ansi_colours" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14eec43e0298190790f41679fe69ef7a829d2a2ddd78c8c00339e84710e435fe" +dependencies = [ + "rgb", +] + [[package]] name = "anstream" version = "0.6.18" @@ -70,11 +79,12 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "3.0.6" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" dependencies = [ "anstyle", + "once_cell", "windows-sys 0.59.0", ] @@ -108,7 +118,7 @@ version = "0.71.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.8.0", "cexpr", "clang-sys", "itertools 0.13.0", @@ -130,9 +140,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" [[package]] name = "block2" @@ -160,6 +170,12 @@ version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +[[package]] +name = "bytemuck" +version = "1.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" + [[package]] name = "byteorder" version = "1.5.0" @@ -678,7 +694,7 @@ version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b903b73e45dc0c6c596f2d37eccece7c1c8bb6e4407b001096387c63d0d93724" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.8.0", "libc", "libgit2-sys", "log", @@ -911,7 +927,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.8.0", "inotify-sys", "libc", ] @@ -988,9 +1004,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.76" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ "once_cell", "wasm-bindgen", @@ -1064,7 +1080,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.8.0", "libc", "redox_syscall", ] @@ -1145,9 +1161,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" +checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" dependencies = [ "adler2", ] @@ -1176,7 +1192,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.8.0", "cfg-if", "cfg_aliases", "libc", @@ -1198,7 +1214,7 @@ version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fee8403b3d66ac7b26aee6e40a897d85dc5ce26f44da36b8b73e987cc52e943" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.8.0", "filetime", "fsevent-sys", "inotify", @@ -1248,9 +1264,9 @@ dependencies = [ [[package]] name = "objc2-encode" -version = "4.0.3" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7891e71393cd1f227313c9379a26a584ff3d7e6e7159e988851f0934c993f0f8" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" [[package]] name = "objc2-foundation" @@ -1258,7 +1274,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.8.0", "block2", "libc", "objc2", @@ -1284,9 +1300,9 @@ checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "openssl-probe" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" @@ -1363,9 +1379,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.28" +version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "924b9a625d6df5b74b0b3cfbb5669b3f62ddf3d46a677ce12b1945471b4ae5c3" +checksum = "6924ced06e1f7dfe3fa48d57b9f74f55d8915f5036121bef647ef4b204895fac" dependencies = [ "proc-macro2", "syn", @@ -1445,7 +1461,7 @@ version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.8.0", ] [[package]] @@ -1490,6 +1506,15 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "rgb" +version = "0.8.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" +dependencies = [ + "bytemuck", +] + [[package]] name = "ring" version = "0.17.8" @@ -1513,11 +1538,11 @@ checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" [[package]] name = "rustix" -version = "0.38.43" +version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.8.0", "errno", "libc", "linux-raw-sys", @@ -1903,6 +1928,7 @@ dependencies = [ name = "tree-sitter-cli" version = "0.25.0" dependencies = [ + "ansi_colours", "anstyle", "anyhow", "bstr", @@ -2041,9 +2067,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +checksum = "11cd88e12b17c6494200a9c1b683a04fcac9573ed74cd1b62aeb2727c5592243" [[package]] name = "unicode-width" @@ -2151,9 +2177,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", "once_cell", @@ -2162,9 +2188,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", @@ -2176,9 +2202,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2186,9 +2212,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", @@ -2199,9 +2225,12 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "wasm-encoder" @@ -2220,7 +2249,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c771866898879073c53b565a6c7b49953795159836714ac56a5befb581227c5" dependencies = [ "ahash", - "bitflags 2.7.0", + "bitflags 2.8.0", "hashbrown 0.14.5", "indexmap", "semver", @@ -2233,7 +2262,7 @@ version = "0.221.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9845c470a2e10b61dd42c385839cdd6496363ed63b5c9e420b5488b77bd22083" dependencies = [ - "bitflags 2.7.0", + "bitflags 2.8.0", "hashbrown 0.15.2", "indexmap", "semver", @@ -2258,7 +2287,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b79302e3e084713249cc5622e8608e7410afdeeea8c8026d04f491d1fab0b4b" dependencies = [ "anyhow", - "bitflags 2.7.0", + "bitflags 2.8.0", "bumpalo", "cc", "cfg-if", @@ -2436,9 +2465,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.76" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/Cargo.toml b/Cargo.toml index c579773e..a5a850e0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -93,6 +93,7 @@ incremental = true codegen-units = 256 [workspace.dependencies] +ansi_colours = "1.2.3" anstyle = "1.0.10" anyhow = "1.0.94" bstr = "1.11.3" diff --git a/cli/Cargo.toml b/cli/Cargo.toml index d1c6172b..1353f815 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -28,6 +28,7 @@ harness = false wasm = ["tree-sitter/wasm", "tree-sitter-loader/wasm"] [dependencies] +ansi_colours.workspace = true anstyle.workspace = true anyhow.workspace = true bstr.workspace = true diff --git a/cli/src/highlight.rs b/cli/src/highlight.rs index cfdd2f76..8611374d 100644 --- a/cli/src/highlight.rs +++ b/cli/src/highlight.rs @@ -5,10 +5,11 @@ use std::{ io::{self, Write as _}, path::{self, Path, PathBuf}, str, - sync::{atomic::AtomicUsize, Arc, LazyLock}, + sync::{atomic::AtomicUsize, Arc}, time::Instant, }; +use ansi_colours::{ansi256_from_rgb, rgb_from_ansi256}; use anstyle::{Ansi256Color, AnsiColor, Color, Effects, RgbColor}; use anyhow::Result; use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer}; @@ -44,9 +45,6 @@ pub const HTML_FOOTER: &str = " "; -static CSS_STYLES_BY_COLOR_ID: LazyLock> = - LazyLock::new(|| serde_json::from_str(include_str!("../vendor/xterm-colors.json")).unwrap()); - #[derive(Debug, Default)] pub struct Style { pub ansi: anstyle::Style, @@ -224,9 +222,8 @@ fn parse_style(style: &mut Style, json: Value) { if let Some(Color::Rgb(RgbColor(red, green, blue))) = style.ansi.get_fg_color() { if !terminal_supports_truecolor() { - style.ansi = style - .ansi - .fg_color(Some(closest_xterm_color(red, green, blue))); + let ansi256 = Color::Ansi256(Ansi256Color(ansi256_from_rgb((red, green, blue)))); + style.ansi = style.ansi.fg_color(Some(ansi256)); } } } @@ -303,7 +300,8 @@ fn write_color(buffer: &mut String, color: Color) { _ => unreachable!(), }, Color::Ansi256(Ansi256Color(n)) => { - write!(buffer, "color: {}", CSS_STYLES_BY_COLOR_ID[n as usize]).unwrap(); + let (r, g, b) = rgb_from_ansi256(n); + write!(buffer, "color: #{r:02x}{g:02x}{b:02x}").unwrap(); } Color::Rgb(RgbColor(r, g, b)) => write!(buffer, "color: #{r:02x}{g:02x}{b:02x}").unwrap(), } @@ -314,30 +312,6 @@ fn terminal_supports_truecolor() -> bool { .is_ok_and(|truecolor| truecolor == "truecolor" || truecolor == "24bit") } -fn closest_xterm_color(red: u8, green: u8, blue: u8) -> Color { - use std::cmp::{max, min}; - - let colors = CSS_STYLES_BY_COLOR_ID - .iter() - .enumerate() - .map(|(color_id, hex)| (color_id as u8, hex_string_to_rgb(hex).unwrap())); - - // Get the xterm color with the minimum Euclidean distance to the target color - // i.e. distance = √ (r2 - r1)² + (g2 - g1)² + (b2 - b1)² - let distances = colors.map(|(color_id, (r, g, b))| { - let r_delta = (max(r, red) - min(r, red)) as u32; - let g_delta = (max(g, green) - min(g, green)) as u32; - let b_delta = (max(b, blue) - min(b, blue)) as u32; - let distance = r_delta.pow(2) + g_delta.pow(2) + b_delta.pow(2); - // don't need to actually take the square root for the sake of comparison - (color_id, distance) - }); - - Color::Ansi256(Ansi256Color( - distances.min_by(|(_, d1), (_, d2)| d1.cmp(d2)).unwrap().0, - )) -} - pub struct HighlightOptions { pub theme: Theme, pub check: bool, @@ -518,12 +492,12 @@ mod tests { ); assert_eq!(style.css, Some("color: #26a69a".to_string())); - // junglegreen gets approximated as darkcyan when the terminal does not support it + // junglegreen gets approximated as cadetblue when the terminal does not support it env::set_var("COLORTERM", ""); parse_style(&mut style, Value::String(JUNGLE_GREEN.to_string())); assert_eq!( style.ansi.get_fg_color(), - Some(Color::Ansi256(Ansi256Color(36))) + Some(Color::Ansi256(Ansi256Color(72))) ); assert_eq!(style.css, Some("color: #26a69a".to_string())); diff --git a/cli/vendor/xterm-colors.json b/cli/vendor/xterm-colors.json deleted file mode 100644 index 47994496..00000000 --- a/cli/vendor/xterm-colors.json +++ /dev/null @@ -1,258 +0,0 @@ -[ - "#000000", - "#800000", - "#008000", - "#808000", - "#000080", - "#800080", - "#008080", - "#c0c0c0", - "#808080", - "#ff0000", - "#00ff00", - "#ffff00", - "#0000ff", - "#ff00ff", - "#00ffff", - "#ffffff", - "#000000", - "#00005f", - "#000087", - "#0000af", - "#0000d7", - "#0000ff", - "#005f00", - "#005f5f", - "#005f87", - "#005faf", - "#005fd7", - "#005fff", - "#008700", - "#00875f", - "#008787", - "#0087af", - "#0087d7", - "#0087ff", - "#00af00", - "#00af5f", - "#00af87", - "#00afaf", - "#00afd7", - "#00afff", - "#00d700", - "#00d75f", - "#00d787", - "#00d7af", - "#00d7d7", - "#00d7ff", - "#00ff00", - "#00ff5f", - "#00ff87", - "#00ffaf", - "#00ffd7", - "#00ffff", - "#5f0000", - "#5f005f", - "#5f0087", - "#5f00af", - "#5f00d7", - "#5f00ff", - "#5f5f00", - "#5f5f5f", - "#5f5f87", - "#5f5faf", - "#5f5fd7", - "#5f5fff", - "#5f8700", - "#5f875f", - "#5f8787", - "#5f87af", - "#5f87d7", - "#5f87ff", - "#5faf00", - "#5faf5f", - "#5faf87", - "#5fafaf", - "#5fafd7", - "#5fafff", - "#5fd700", - "#5fd75f", - "#5fd787", - "#5fd7af", - "#5fd7d7", - "#5fd7ff", - "#5fff00", - "#5fff5f", - "#5fff87", - "#5fffaf", - "#5fffd7", - "#5fffff", - "#870000", - "#87005f", - "#870087", - "#8700af", - "#8700d7", - "#8700ff", - "#875f00", - "#875f5f", - "#875f87", - "#875faf", - "#875fd7", - "#875fff", - "#878700", - "#87875f", - "#878787", - "#8787af", - "#8787d7", - "#8787ff", - "#87af00", - "#87af5f", - "#87af87", - "#87afaf", - "#87afd7", - "#87afff", - "#87d700", - "#87d75f", - "#87d787", - "#87d7af", - "#87d7d7", - "#87d7ff", - "#87ff00", - "#87ff5f", - "#87ff87", - "#87ffaf", - "#87ffd7", - "#87ffff", - "#af0000", - "#af005f", - "#af0087", - "#af00af", - "#af00d7", - "#af00ff", - "#af5f00", - "#af5f5f", - "#af5f87", - "#af5faf", - "#af5fd7", - "#af5fff", - "#af8700", - "#af875f", - "#af8787", - "#af87af", - "#af87d7", - "#af87ff", - "#afaf00", - "#afaf5f", - "#afaf87", - "#afafaf", - "#afafd7", - "#afafff", - "#afd700", - "#afd75f", - "#afd787", - "#afd7af", - "#afd7d7", - "#afd7ff", - "#afff00", - "#afff5f", - "#afff87", - "#afffaf", - "#afffd7", - "#afffff", - "#d70000", - "#d7005f", - "#d70087", - "#d700af", - "#d700d7", - "#d700ff", - "#d75f00", - "#d75f5f", - "#d75f87", - "#d75faf", - "#d75fd7", - "#d75fff", - "#d78700", - "#d7875f", - "#d78787", - "#d787af", - "#d787d7", - "#d787ff", - "#d7af00", - "#d7af5f", - "#d7af87", - "#d7afaf", - "#d7afd7", - "#d7afff", - "#d7d700", - "#d7d75f", - "#d7d787", - "#d7d7af", - "#d7d7d7", - "#d7d7ff", - "#d7ff00", - "#d7ff5f", - "#d7ff87", - "#d7ffaf", - "#d7ffd7", - "#d7ffff", - "#ff0000", - "#ff005f", - "#ff0087", - "#ff00af", - "#ff00d7", - "#ff00ff", - "#ff5f00", - "#ff5f5f", - "#ff5f87", - "#ff5faf", - "#ff5fd7", - "#ff5fff", - "#ff8700", - "#ff875f", - "#ff8787", - "#ff87af", - "#ff87d7", - "#ff87ff", - "#ffaf00", - "#ffaf5f", - "#ffaf87", - "#ffafaf", - "#ffafd7", - "#ffafff", - "#ffd700", - "#ffd75f", - "#ffd787", - "#ffd7af", - "#ffd7d7", - "#ffd7ff", - "#ffff00", - "#ffff5f", - "#ffff87", - "#ffffaf", - "#ffffd7", - "#ffffff", - "#080808", - "#121212", - "#1c1c1c", - "#262626", - "#303030", - "#3a3a3a", - "#444444", - "#4e4e4e", - "#585858", - "#626262", - "#6c6c6c", - "#767676", - "#808080", - "#8a8a8a", - "#949494", - "#9e9e9e", - "#a8a8a8", - "#b2b2b2", - "#bcbcbc", - "#c6c6c6", - "#d0d0d0", - "#dadada", - "#e4e4e4", - "#eeeeee" -]