From bb3792b300ef929fcab7a4762c0316a84e7777be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=98=BF=E8=B1=AA?= <504595380@qq.com> Date: Sun, 27 Oct 2024 18:47:51 +0800 Subject: [PATCH] support ansi minify (#19) * support ansi minify * add to_ans test * wasm: add to_ans * wasm: add to_ans * to_ans: add test --- ansi2-wasm/src-ts/cli.ts | 7 +- ansi2-wasm/src-ts/wasm/index.d.ts | 7 ++ ansi2-wasm/src/lib.rs | 5 + ansi2/src/ans.rs | 94 ++++++++++++++++++ ansi2/src/color.rs | 21 ++++ ansi2/src/lex.rs | 10 ++ ansi2/src/lib.rs | 24 ++++- ansi2/src/main.rs | 51 +++++----- .../snapshots/ansi2__test__fastfetch-2.snap | 4 +- .../snapshots/ansi2__test__fastfetch-3.snap | 4 +- ansi2/src/text.rs | 9 +- assets/24bit-color.min.ans | 3 + assets/8bit-color.min.ans | 17 ++++ assets/ansi-default.min.ans | 9 ++ assets/colortable.min.ans | 22 ++++ assets/hyperlink-demo.min.ans | 92 +++++++++++++++++ assets/nu-ls.min.ans | 11 ++ assets/take-my-ansi.ans | Bin 4307 -> 7867 bytes assets/update.sh | 2 + assets/vitest.min.ans | 35 +++++++ assets/win11.min.ans | 22 ++++ 21 files changed, 410 insertions(+), 39 deletions(-) create mode 100644 ansi2/src/ans.rs create mode 100644 assets/24bit-color.min.ans create mode 100644 assets/8bit-color.min.ans create mode 100644 assets/ansi-default.min.ans create mode 100644 assets/colortable.min.ans create mode 100644 assets/hyperlink-demo.min.ans create mode 100644 assets/nu-ls.min.ans create mode 100644 assets/vitest.min.ans create mode 100644 assets/win11.min.ans diff --git a/ansi2-wasm/src-ts/cli.ts b/ansi2-wasm/src-ts/cli.ts index db15f59..94a733a 100644 --- a/ansi2-wasm/src-ts/cli.ts +++ b/ansi2-wasm/src-ts/cli.ts @@ -1,4 +1,4 @@ -import { to_svg, to_html, to_text, Theme } from "./wasm" +import { to_svg, to_html, to_text, Theme, to_ans } from "./wasm" import { readFileSync, existsSync } from "node:fs" import { optimize } from "svgo" import { Mode } from "./wasm" @@ -7,7 +7,7 @@ import * as t from "typanion" import { Command, Option, Cli, Builtins } from "clipanion" const isInteger = t.cascade(t.isNumber(), [t.isInteger()]) -const isFormat = t.cascade(t.isEnum(["html", "svg", "text"])) +const isFormat = t.cascade(t.isEnum(["html", "svg", "text", "ans"])) const isTheme = t.cascade(t.isEnum(["vscode", "ubuntu", "vga", "xterm"])) const isLengthAdjust = t.cascade(t.isEnum(["spacing", "spacingAndGlyphs"])) const isColor = t.cascade( @@ -129,6 +129,9 @@ class AnsiCmd extends Command { case "text": { process.stdout.write(to_text(input, width)) } + case "ans": { + process.stdout.write(to_ans(input, width, compress)) + } } } } diff --git a/ansi2-wasm/src-ts/wasm/index.d.ts b/ansi2-wasm/src-ts/wasm/index.d.ts index a144428..f4d5ac6 100644 --- a/ansi2-wasm/src-ts/wasm/index.d.ts +++ b/ansi2-wasm/src-ts/wasm/index.d.ts @@ -31,6 +31,13 @@ export function to_html(s: string, theme: Theme, width?: number, font?: string, * @returns {string} */ export function to_text(s: string, width?: number): string; +/** + * @param {string} s + * @param {number | undefined} [width] + * @param {boolean | undefined} [compress] + * @returns {string} + */ +export function to_ans(s: string, width?: number, compress?: boolean): string; export enum Mode { Dark = 0, Light = 1, diff --git a/ansi2-wasm/src/lib.rs b/ansi2-wasm/src/lib.rs index 9d92b0e..1451d1a 100644 --- a/ansi2-wasm/src/lib.rs +++ b/ansi2-wasm/src/lib.rs @@ -63,3 +63,8 @@ pub fn to_html( pub fn to_text(s: String, width: Option) -> String { ansi2::text::to_text(&s, width) } + +#[wasm_bindgen] +pub fn to_ans(s: String, width: Option, compress: Option) -> String { + ansi2::ans::to_ans(&s, width, compress.unwrap_or(false)) +} diff --git a/ansi2/src/ans.rs b/ansi2/src/ans.rs new file mode 100644 index 0000000..3e3e3f3 --- /dev/null +++ b/ansi2/src/ans.rs @@ -0,0 +1,94 @@ +use crate::{color::AnsiColor, Canvas, Node}; + +pub fn to_ans>(str: S, width: Option, compress: bool) -> String { + let s = str.as_ref(); + let canvas = Canvas::new(s, width); + + let iter = if compress { + canvas.minify().into_iter() + } else { + canvas.pixels.into_iter() + }; + + let mut text: Vec = Vec::new(); + + let mut last_node = Node::default(); + + for row in iter { + let mut row_str = Vec::new(); + for c in row.iter() { + if !last_node.same_style(c) { + // FIXME: Find the minimum distance between two styles + row_str.push("\x1b[0m".to_string()); + if c.bold { + row_str.push("\x1b[1m".to_string()); + } + if c.italic { + row_str.push("\x1b[3m".to_string()); + } + if c.dim { + row_str.push("\x1b[2m".to_string()); + } + if c.underline { + row_str.push("\x1b[4m".to_string()); + } + if c.hide { + row_str.push("\x1b[8m".to_string()); + } + if c.blink { + row_str.push("\x1b[5m".to_string()); + } + + row_str.push(match c.color { + AnsiColor::Default => "".to_string(), + AnsiColor::Color8(color8) => format!("\x1b[{}m", color8.to_u8()), + AnsiColor::Color256(n) => format!("\x1b[38;5;{}m", n), + AnsiColor::Rgb(r, g, b) => format!("\x1b[38;2;{};{};{}m", r, g, b), + }); + + row_str.push(match c.bg_color { + AnsiColor::Default => "".to_string(), + AnsiColor::Color8(color8) => format!("\x1b[{}m", color8.to_u8() + 10), + AnsiColor::Color256(n) => format!("\x1b[48;5;{}m", n), + AnsiColor::Rgb(r, g, b) => format!("\x1b[48;2;{};{};{}m", r, g, b), + }); + } + row_str.push(c.text.clone()); + last_node = c.clone(); + } + text.push(row_str.into_iter().collect()); + } + text.join("\n") +} + +#[cfg(test)] +mod test { + use std::path::Path; + + use crate::{ans::to_ans, Canvas}; + + #[test] + fn test() { + let cargo_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); + let assets_dir = Path::new(&cargo_dir).parent().unwrap().join("assets"); + let v = std::fs::read_dir(assets_dir).unwrap(); + for i in v { + let p = i.unwrap().path().to_string_lossy().to_string(); + if !p.ends_with(".ans") { + continue; + } + if p.ends_with(".min.ans") { + continue; + } + let s = std::fs::read_to_string(&p).unwrap(); + let min = to_ans(&s, None, true); + + let c1 = Canvas::new(&s, None); + let c2 = Canvas::new(&min, None); + assert_eq!(c1, c2); + + let min2 = to_ans(&min, None, true); + assert_eq!(min2, min); + } + } +} diff --git a/ansi2/src/color.rs b/ansi2/src/color.rs index bf49241..3371f10 100644 --- a/ansi2/src/color.rs +++ b/ansi2/src/color.rs @@ -109,6 +109,27 @@ impl Color8 { _ => Color8::Black, } } + + pub fn to_u8(&self) -> u8 { + match self { + Color8::Black => 30, + Color8::Red => 31, + Color8::Green => 32, + Color8::Yellow => 33, + Color8::Blue => 34, + Color8::Magenta => 35, + Color8::Cyan => 36, + Color8::White => 37, + Color8::BrightBlack => 90, + Color8::BrightRed => 91, + Color8::BrightGreen => 92, + Color8::BrightYellow => 93, + Color8::BrightBlue => 94, + Color8::BrightMagenta => 95, + Color8::BrightCyan => 96, + Color8::BrightWhite => 97, + } + } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] pub enum AnsiColor { diff --git a/ansi2/src/lex.rs b/ansi2/src/lex.rs index 92d1d35..c34b0a0 100644 --- a/ansi2/src/lex.rs +++ b/ansi2/src/lex.rs @@ -335,6 +335,12 @@ fn parse_sgr3(input: &str) -> IResult<&str, Token> { let b = front.parse().unwrap_or(0); let c = background.parse().unwrap_or(0); + if a == 38 && b == 5 { + return Ok((rem, Token::ColorForeground(AnsiColor::from_u8(c)))); + } + if a == 48 && b == 5 { + return Ok((rem, Token::ColorBackground(AnsiColor::from_u8(c)))); + } Ok(( rem, Token::List(vec![get_sgr(a), get_token_color(b), get_token_color(c)]), @@ -414,6 +420,10 @@ fn parse_sgr5(input: &str) -> IResult<&str, Token> { if ctrl == 38 && ty == 2 { return Ok((rem, Token::ColorForeground(AnsiColor::Rgb(r, g, b)))); } + + if ctrl == 48 && ty == 2 { + return Ok((rem, Token::ColorBackground(AnsiColor::Rgb(r, g, b)))); + } todo!() } diff --git a/ansi2/src/lib.rs b/ansi2/src/lib.rs index 95ffcef..9888bd0 100644 --- a/ansi2/src/lib.rs +++ b/ansi2/src/lib.rs @@ -1,3 +1,4 @@ +pub mod ans; pub mod color; #[allow(clippy::too_many_arguments)] pub mod css; @@ -10,7 +11,7 @@ use color::AnsiColor; use lex::{parse_ansi, Token}; use std::{collections::VecDeque, vec}; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Default, PartialEq, Eq)] pub struct Node { pub bg_color: AnsiColor, pub color: AnsiColor, @@ -36,7 +37,7 @@ impl Node { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Default, PartialEq, Eq)] pub struct Canvas { pub pixels: Vec>, pub w: usize, @@ -44,9 +45,7 @@ pub struct Canvas { } fn set_node(v: &mut Vec>, node: Node, x: usize, y: usize) { - while y >= v.len() { - v.push(Vec::new()); - } + ensure_height(v, y); let row = &mut v[y]; while x >= row.len() { @@ -67,6 +66,12 @@ fn set_node(v: &mut Vec>, node: Node, x: usize, y: usize) { row[x] = node; } +fn ensure_height(v: &mut Vec>, h: usize) { + while v.len() <= h { + v.push(Vec::new()); + } +} + impl Canvas { pub fn new>(str: S, max_width: Option) -> Self { let s = str.as_ref(); @@ -114,7 +119,9 @@ impl Canvas { Token::LineFeed => { cur_y += 1; cur_x = 0; + ensure_height(&mut pixels, cur_y); } + Token::Char(c) => { let node = Node { text: c.into(), @@ -182,6 +189,7 @@ impl Canvas { Token::CursorUp(c) => cur_y = cur_y.saturating_sub(c as usize), Token::CursorDown(c) => { cur_y += c as usize; + ensure_height(&mut pixels, cur_y); } Token::CursorBack(c) => cur_x = cur_x.saturating_sub(c as usize), Token::CursorForward(c) => { @@ -190,6 +198,7 @@ impl Canvas { cur_x %= max_width; cur_y += 1; } + ensure_height(&mut pixels, cur_y); } Token::Backspace => cur_x = cur_x.saturating_sub(1), Token::Tab => { @@ -204,6 +213,7 @@ impl Canvas { cur_x %= max_width; cur_y += 1; } + ensure_height(&mut pixels, cur_y); } Token::CarriageReturn => cur_x = 0, @@ -211,15 +221,18 @@ impl Canvas { Token::CursorNextLine(n) => { cur_y += n as usize; cur_x = 0; + ensure_height(&mut pixels, cur_y); } Token::CursorPreviousLine(n) => { cur_y = cur_y.saturating_sub(n as usize); cur_x = 0; + ensure_height(&mut pixels, cur_y); } Token::CursorHorizontalAbsolute(n) => cur_x = (n - 1).max(0) as usize, Token::CursorPosition(x, y) => { cur_x = x as usize; cur_y = y as usize; + ensure_height(&mut pixels, cur_y); } Token::SlowBlink | Token::RapidBlink => blink = true, Token::Reverse => { @@ -267,6 +280,7 @@ impl Canvas { if i == '\n' { cur_x = 0; cur_y += 1; + ensure_height(&mut pixels, cur_y); continue; } diff --git a/ansi2/src/main.rs b/ansi2/src/main.rs index af0e2e2..c3716bf 100644 --- a/ansi2/src/main.rs +++ b/ansi2/src/main.rs @@ -1,3 +1,4 @@ +use ansi2::ans::to_ans; use ansi2::{css::Mode, theme::Theme}; use ansi2::{html::to_html, svg::to_svg, text::to_text}; use base64::prelude::BASE64_STANDARD; @@ -11,6 +12,7 @@ enum Format { Svg, Html, Text, + Ans, } #[derive(Parser, Debug, Clone)] @@ -48,20 +50,26 @@ struct Args { fn main() { let args: Args = Args::parse(); - - let format = args.format.unwrap_or(Format::Svg); - let theme = args.theme.unwrap_or(Theme::Vscode); - let mode = args.mode.map(|m| match m { - Mode::Dark => ansi2::css::Mode::Dark, - Mode::Light => ansi2::css::Mode::Light, - }); - let width = args.width; + let Args { + width, + format, + theme, + mode, + font, + compress, + light_bg, + dark_bg, + font_size, + length_adjust, + } = args; + let format = format.unwrap_or(Format::Svg); + let theme = theme.unwrap_or(Theme::Vscode); let mut buf = Vec::new(); std::io::stdin() .read_to_end(&mut buf) .expect("can't read string from stdin"); - let base64 = args.font.map(|font_url| { + let base64 = font.map(|font_url| { if font_url.starts_with("http") { return font_url; } @@ -84,12 +92,12 @@ fn main() { width, base64, mode, - args.light_bg, - args.dark_bg, - args.font_size, - args.length_adjust, + light_bg, + dark_bg, + font_size, + length_adjust, ); - if args.compress { + if compress { svg = osvg::osvg( &svg, Some( @@ -112,18 +120,9 @@ fn main() { } svg } - Format::Html => to_html( - &s, - theme, - width, - base64, - mode, - args.light_bg, - args.dark_bg, - args.font_size, - ), + Format::Html => to_html(&s, theme, width, base64, mode, light_bg, dark_bg, font_size), Format::Text => to_text(&s, width), + Format::Ans => to_ans(&s, width, compress), }; - - println!("{}", output); + print!("{}", output); } diff --git a/ansi2/src/snapshots/ansi2__test__fastfetch-2.snap b/ansi2/src/snapshots/ansi2__test__fastfetch-2.snap index e2028e9..0aff5f4 100644 --- a/ansi2/src/snapshots/ansi2__test__fastfetch-2.snap +++ b/ansi2/src/snapshots/ansi2__test__fastfetch-2.snap @@ -3,7 +3,9 @@ source: ansi2/src/lib.rs expression: canvas --- Canvas { - pixels: [], + pixels: [ + [], + ], w: 48, h: 1, } diff --git a/ansi2/src/snapshots/ansi2__test__fastfetch-3.snap b/ansi2/src/snapshots/ansi2__test__fastfetch-3.snap index 2575438..8627601 100644 --- a/ansi2/src/snapshots/ansi2__test__fastfetch-3.snap +++ b/ansi2/src/snapshots/ansi2__test__fastfetch-3.snap @@ -2,4 +2,6 @@ source: ansi2/src/lib.rs expression: canvas.minify() --- -[] +[ + [], +] diff --git a/ansi2/src/text.rs b/ansi2/src/text.rs index fc28c37..5a68752 100644 --- a/ansi2/src/text.rs +++ b/ansi2/src/text.rs @@ -3,12 +3,13 @@ use crate::Canvas; pub fn to_text>(str: S, width: Option) -> String { let s = str.as_ref(); let canvas = Canvas::new(s, width); - let mut text = String::new(); + let mut text: Vec = Vec::new(); for row in canvas.pixels.iter() { + let mut row_str = String::new(); for c in row.iter() { - text.push_str(&c.text) + row_str.push_str(&c.text) } - text.push('\n') + text.push(row_str); } - text + text.join("\n") } diff --git a/assets/24bit-color.min.ans b/assets/24bit-color.min.ans new file mode 100644 index 0000000..b192713 --- /dev/null +++ b/assets/24bit-color.min.ans @@ -0,0 +1,3 @@ +โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ +โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ +โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ \ No newline at end of file diff --git a/assets/8bit-color.min.ans b/assets/8bit-color.min.ans new file mode 100644 index 0000000..ceaf625 --- /dev/null +++ b/assets/8bit-color.min.ans @@ -0,0 +1,17 @@ +โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ +โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ + +โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ +โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ +โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ +โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ +โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ +โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ +โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ +โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ +โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ +โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ +โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ +โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ + +โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ \ No newline at end of file diff --git a/assets/ansi-default.min.ans b/assets/ansi-default.min.ans new file mode 100644 index 0000000..680193e --- /dev/null +++ b/assets/ansi-default.min.ans @@ -0,0 +1,9 @@ +โ•ญโ”€#โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€nameโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€previewโ”€โ”ฌโ”€short nameโ”€โ”ฌโ”€โ”€โ”€codeโ”€โ”€โ”€โ•ฎ +โ”‚ 0 โ”‚ default โ”‚ NUSHELL โ”‚ def โ”‚ \e[39m โ”‚ +โ”‚ 1 โ”‚ default_bold โ”‚ NUSHELL โ”‚ defb โ”‚ \e[1;39m โ”‚ +โ”‚ 2 โ”‚ default_underline โ”‚ NUSHELL โ”‚ defu โ”‚ \e[4;39m โ”‚ +โ”‚ 3 โ”‚ default_italic โ”‚ NUSHELL โ”‚ defi โ”‚ \e[3;39m โ”‚ +โ”‚ 4 โ”‚ default_dimmed โ”‚ NUSHELL โ”‚ defd โ”‚ \e[2;39m โ”‚ +โ”‚ 5 โ”‚ default_reverse โ”‚ NUSHELL โ”‚ defr โ”‚ \e[7;39m โ”‚ +โ”‚ 6 โ”‚ bg_default โ”‚ NUSHELL โ”‚ bg_def โ”‚ \e[49m โ”‚ +โ•ฐโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ \ No newline at end of file diff --git a/assets/colortable.min.ans b/assets/colortable.min.ans new file mode 100644 index 0000000..7fbef3a --- /dev/null +++ b/assets/colortable.min.ans @@ -0,0 +1,22 @@ + + 40m 41m 42m 43m 44m 45m 46m 47m 49m +30m  30;40m  30;41m  30;42m  30;43m  30;44m  30;45m  30;46m  30;47m  30;49m +31m  31;40m  31;41m  31;42m  31;43m  31;44m  31;45m  31;46m  31;47m  31;49m +32m  32;40m  32;41m  32;42m  32;43m  32;44m  32;45m  32;46m  32;47m  32;49m +33m  33;40m  33;41m  33;42m  33;43m  33;44m  33;45m  33;46m  33;47m  33;49m +34m  34;40m  34;41m  34;42m  34;43m  34;44m  34;45m  34;46m  34;47m  34;49m +35m  35;40m  35;41m  35;42m  35;43m  35;44m  35;45m  35;46m  35;47m  35;49m +36m  36;40m  36;41m  36;42m  36;43m  36;44m  36;45m  36;46m  36;47m  36;49m +37m  37;40m  37;41m  37;42m  37;43m  37;44m  37;45m  37;46m  37;47m  37;49m +39m  39;40m  39;41m  39;42m  39;43m  39;44m  39;45m  39;46m  39;47m  39;49m + + + 100m 101m 102m 103m 104m 105m 106m 107m +90m  90;100m  90;101m  90;102m  90;103m  90;104m  90;105m  90;106m  90;107m +91m  91;100m  91;101m  91;102m  91;103m  91;104m  91;105m  91;106m  91;107m +92m  92;100m  92;101m  92;102m  92;103m  92;104m  92;105m  92;106m  92;107m +93m  93;100m  93;101m  93;102m  93;103m  93;104m  93;105m  93;106m  93;107m +94m  94;100m  94;101m  94;102m  94;103m  94;104m  94;105m  94;106m  94;107m +95m  95;100m  95;101m  95;102m  95;103m  95;104m  95;105m  95;106m  95;107m +96m  96;100m  96;101m  96;102m  96;103m  96;104m  96;105m  96;106m  96;107m +97m  97;100m  97;101m  97;102m  97;103m  97;104m  97;105m  97;106m  97;107m \ No newline at end of file diff --git a/assets/hyperlink-demo.min.ans b/assets/hyperlink-demo.min.ans new file mode 100644 index 0000000..29cab63 --- /dev/null +++ b/assets/hyperlink-demo.min.ans @@ -0,0 +1,92 @@ +Tests for gnome-terminal #779734 and iTerm2 #5158 +โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• + +commit a9b0b4c75a6dc7282f7cfcaef71413d69f7f0731 +Author: Egmont Koblinger <egmont@gmail.com> +Date: Sat Oct 24 00:12:22 2015 +0200 + + widget: Implement smooth scrolling + + Bug #746690 + +commit 6a74baeaabb0a1ce54444611b324338f94721a5c +Merge: 3fac446 56ea581 +Author: Christian Persch <chpe@gnome.org> +Date: Mon Apr 27 13:48:52 2015 +0200 + + Merge branch 'work-html' into merge-html + +A file with a % sign in its name (escaped as %25) +Icons: Theme Graphics Star Exit Terminal +Backgrounds: Bokeh Chmiri Ivy Flower Iceland Icescape Mirror Road Sandstone Stones Waterfalls Waves + +Wiki page of ๏ฟฝ (unescaped raw Latin-1; invalid UTF-8) +Wiki page of ร (unescaped raw UTF-8) +Wiki page of ร (escaped as %C3%81) +Wiki page of % (escaped as %25) +http://ุงู„ู…ุบุฑุจ.icom.museum (with URI-escaped domain name) +http://xn--4wa8awb4637h.org (ฮ ฮฑฮฝ่ชž.org) + +Two adjacent links pointing to the same URL: foofoo +Two adjacent links pointing to different URLs: foobar + +The same two without closing the first link: foo]8;;http://example.com/foo\foo foo]8;;http://example.com/bar\bar + +A URL wrapping to the next line, and a trailing whitespace: foo +bar + +Multi-colour link also tests that "\e[m" or "\e[0m" does not terminate the link + +Soft reset "\e[!p" resets attributes and terminates link: foo[!pbar + +]8;;http://example.com/width\Some CJK and combining accents: ไ€€ไ€ไ€‚cฬgฬ‚mฬƒnฬ„oฬ… + +(Introducing the "under_score" character for even more fun) + +Explicit and implicit link: http://example.com/under_score +Explicit and implicit link with different targets: http://example.com/implicit_under_score +Explicit and implicit link, broken into two lines: http://examp +le.com/under_score + +Explicitly underlined links ("\e[4m"): +Explicit link only: I'm an explicit link with under_score +Implicit link only: http://example.com/under_score +Both: http://example.com/under_score + +Conflicting explicit and implicit links: http://example.com/foobar-explicit-rest + +Invisible explicit link: ยซCan you see me?ยป +Invisible implicit link: ยซhttp://example.com/how_about_meยป + +Explicit link with stupid target + +URL of 100 bytes +URL of 200 bytes +URL of 500 bytes +URL of 1000 bytes +URL of 1500 bytes +URL of 2000 bytes +URL of 2083 bytes +URL of 2084 bytes + +ID of 250 bytes once, twice +ID of 251 bytes once, twice + +ID of 250 bytes + URL of 2083 bytes +ID of 251 bytes + URL of 2083 bytes +ID of 250 bytes + URL of 2084 bytes +ID of 251 bytes + URL of 2084 bytes + +move right + +Alternating URIs, all with the same ID. Either all foos or all bars should be underlined on hover: +foobarfoobarfoobarfoo + +Screenshot from an imaginary text editor: +โ•”โ• file1 โ•โ•โ•โ•โ•— +โ•‘ โ•”โ• file2 โ•โ•โ•โ•— +โ•‘http://exaโ•‘Lorem ipsumโ•‘ +โ•‘le.com โ•‘ dolor sit โ•‘ +โ•‘ โ•‘amet, conseโ•‘ +โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•‘ctetur adipโ•‘ + โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• \ No newline at end of file diff --git a/assets/nu-ls.min.ans b/assets/nu-ls.min.ans new file mode 100644 index 0000000..4db4b60 --- /dev/null +++ b/assets/nu-ls.min.ans @@ -0,0 +1,11 @@ +โ•ญโ”€#โ”€โ”ฌโ”€โ”€โ”€โ”€nameโ”€โ”€โ”€โ”€โ”ฌโ”€typeโ”€โ”ฌโ”€โ”€sizeโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€modifiedโ”€โ”€โ”€โ•ฎ +โ”‚ 0 โ”‚ Cargo.lock โ”‚ file โ”‚ 60.5 KB โ”‚ 12 hours ago โ”‚ +โ”‚ 1 โ”‚ Cargo.toml โ”‚ file โ”‚ 463 B โ”‚ 12 hours ago โ”‚ +โ”‚ 2 โ”‚ LICENSE โ”‚ file โ”‚ 1.1 KB โ”‚ 12 hours ago โ”‚ +โ”‚ 3 โ”‚ README.md โ”‚ file โ”‚ 4.2 KB โ”‚ 12 hours ago โ”‚ +โ”‚ 4 โ”‚ benches โ”‚ dir โ”‚ 128 B โ”‚ 12 hours ago โ”‚ +โ”‚ 5 โ”‚ src โ”‚ dir โ”‚ 448 B โ”‚ 12 hours ago โ”‚ +โ”‚ 6 โ”‚ target โ”‚ dir โ”‚ 256 B โ”‚ 11 hours ago โ”‚ +โ”‚ 7 โ”‚ tests โ”‚ dir โ”‚ 1.0 KB โ”‚ 12 hours ago โ”‚ +โ”‚ 8 โ”‚ toolkit.nu โ”‚ file โ”‚ 436 B โ”‚ 12 hours ago โ”‚ +โ•ฐโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ \ No newline at end of file diff --git a/assets/take-my-ansi.ans b/assets/take-my-ansi.ans index fb1c6d595f8df5e511b1257cc01c4e3f9dc86aa5..86da04a1b8c0e377f9d807d13f03d83b71b7fc84 100644 GIT binary patch literal 7867 zcmc&(&2AG(5PpyKWgcLK96OLhP8I}#z*!_G2b2Sf#Lq@60}9C@Zw0xpco46&kFc+> zUsZKgS9ed3d+c36QQTAi_0`wi6EnG(t|u1<$Mfm>pYMOxekK=(N2H&?T5QDUSi~w) zWi3o5pIpr67H-Z7%tCeeOciGFBNsggZG++%y>+Ou-hj3!jnwT#-&M_>f`d?2`+;Oi zQ|j`6WO{r!a$*+N7R@|xRl=DIl~1LBg&bI@o0y~_O@@9sCaGhG?3zF`kmm=e`ikE( zEkgG9p2Zyt1?*>Q;vb^V$K*J!UQM{K#0fcmp2-Mc@G( zn|tqt1GLy`kj>VA-#gW=Kq)vrF+h6mk3TVf(HMWG1{IF?RJk}^J%6xz zy@FIQ11e^H5F$u-&LZ3+Tf1(93RaP27%S4c@gZ&CA_^OGd}Y-!oS6)dj!Af8PDETi z7_uLod7{j5g`MJ<<)rAKA`LcV6CQiBV8bRhmMx$oV>>+D;=z`P+(HB56=bcUh^I6Z zwyomB?o>U?#S1RBx5q;nH%$QYFWdJ7xfNC}T0qo#iK(H;jG(zina4|*1zs>}9l>=c zfbC#+iKJJEZtV)V0XJxkej%n57xZ{g3tlR=z9^N|x&l}MK6eWEcZt#wE&~TfY2PbJ zVV96c>(#UKv+n#=w>W)5Q%p`G3*+06WhncnHp;_X_i%`BAp<_${Hb5^hX z3Mnf{>hZ<{F_!OFAf}~Z6_;>`S_6JTyh(6_z>OePb3pGsb{%W$^-NF7A>+L(LH?om zz2((}R7_1*le;n1Od#)a{)+7`345~y2>P@1dSt?Jm4Hora3Kg0E1p*=8k=vOV?r_} z(CjOaDjF`RU7PS*+yY95jewb+ z(_%??P_4i!@xyEawGb%Jr&Sb@BXGvG@cMw53Lyv7mtQ3_KJ~5)8yI~PhMZdx?*BV< zR-FwOsa**}=%`69%=Ri$9Fy4G7#((@$LtSo$+5woO!kVX=oEWcY>_K@kL3gkV2UWK z_T#5x6>o@`D6IHHDr@|W2HI+Jxy#T{DyX6)>v)f-3lss4>$ z?{TTgHiN|8`EB^v7!EIQQYESt>MG)Fc-8dp4aWXE^sI#2^P%$oDik4Ny4c3=C`g9ih0g2BE<4|shN#M zs4W~0F!}GG$nyR2__yWh+0*O0?)~+rb@%l4=Jxt>efev*dUP_+|2whzyjq+;KABEe zzu(?;=byXFk8iuP%RkEpY*==k!@ D;_PFt literal 4307 zcmZ`+%WfM-5R`H^kZYpLe1H)wxk`B8iLvEGNT?W~6u{6y5D+I3g0%x#I_R$?{?0DR zKOtOIJv}qKB=$+LPtj3YH#VO3wv~PTPmJl%bzOYkx4TW3UF%SVVG9GykT5j989O1Px3beqe zVm4v;&}4c#%+Dah8yOn1VBS+Oh3+~#g5L~otF1NHEPma9%euCB7y(Z@mIus=PhRm6 z-PGW_h~``TyDy6N_k<#m;3IbYutcBXaqos{|rRTUkYyWy0mWAtwOAVX{y9b(i22#onR4 zWY2k{z!P@eVF#}2x*2b>Z$NuFqb0_+BWy8|fQ;moB(%sRuA4Ll>A?fwrqnQi0kd)n zlv&Kl%~-Zc<9EjnpwtKi9vOgW@s~FRzl4GGM^PvHK|?1Abb!br=+5+m<5ia45VS`U zZp1AM(cAL`a1|8}$>B+>7+_uEB3b=hR1%cjt{Z!&$)=Z1T*O+bu$60!*mye`oDe(| zW)6ZnL662S0`9q+z9E+;K3+-dJ1Y&88rIBo(ky42@^UVbrGp6Se4G&>!$$#+OcbUgazV*$Wx$GH!EPZ|K*XfEoc(qd<{yy6 z;+$5zbqdnYVyV|2_$Rfz)>IDVNZVd@FiV2t4jTp*(!0fpwHQR>&%P ztjx<-QaWSRMi@4e{6Jec#vl=Y+_FldsgV!Xag(CL;w5;N4qiT3n-0zjQO9m_F!`KJ z#uP_8spGb(Xhehf)R)iE6^o$CuoOPE4DCDUor{NvMna#Q49OYiirC_US{4}1-#CI? zTp6KkR>0H4C%=4IfiE@-+)7MLH55aHniP$?qD;F*O8D5KC?O^;s>u#MY>9FzJ#V*N zccWE9+bf8fiOv_N4d>yE<<)IqRsBxMsWp=X8)1dpdS6T`=7h80suwXK*I>hPDgjOL z3ew5c0P(dO_sz?iU#Cg01$z535OUx}pBy!8p+M%J#-&j7O_aNfX{04-G>_onQX*4z zG+DES4(}vCaLAE~LR2~!r7ub5teLPwG79XhSs=>@-d+R|K9)g}_e4t@GX)-|0eTpr z&|-uaNF4m9_YO&NsQNC+TWCqeBYy_d&of<(;}u90WRNi9CF<&;H?@e5liH^)jku*+T; z+Hkp4f%2#Az#>QG2IU`Bg@l1NUApLvyr&|;SRCKbi3A?=>pRs^;xO-rN=CEq-~2JZ zxO{j26#l;d+=O?J50Ce^&F$;3`01=3{=i=;2>925k``^bf ze+u)@pFTe2gTKF>F_eb9y@j3qH{O5W2 K^Ou=s`R6O1j%iN- diff --git a/assets/update.sh b/assets/update.sh index 5173dee..7709019 100755 --- a/assets/update.sh +++ b/assets/update.sh @@ -3,6 +3,8 @@ for i in win11 vitest 8bit-color 24bit-color nu-ls ansi-default colortable hyperlink-demo do cat "$i.ans" | node ../ansi2-wasm/bin/cli.js -c > "$i.svg" + cat "$i.ans" | node ../ansi2-wasm/bin/cli.js -c -f=ans > "$i.min.ans" + cat "$i.ans" | node ../ansi2-wasm/bin/cli.js --mode=light -c > "$i-light.svg" cat "$i.ans" | node ../ansi2-wasm/bin/cli.js --mode=dark -c > "$i-dark.svg" diff --git a/assets/vitest.min.ans b/assets/vitest.min.ans new file mode 100644 index 0000000..355a28f --- /dev/null +++ b/assets/vitest.min.ans @@ -0,0 +1,35 @@ + +> @xwat/bench@0.2.2 bench:run C:\wt\xwat\xwat-bench +> vitest bench --run + + + RUN  v2.0.3 C:/wt/xwat/xwat-bench + + โœ“ bench/invert.bench.tsx > gray 2509ms + name   hz  min  max  mean  p75  p99  p995  p999  rme samples + ยท js 48.4839 20.3462 21.0757 20.6254 20.7499 21.0757 21.0757 21.0757 ยฑ0.40%  25  slowest + ยท wasm  132.98  7.2320  8.2683  7.5197  7.6484  8.2683  8.2683  8.2683 ยฑ0.89%  67 + ยท wasm-simd  269.44  3.4001  4.3596  3.7113  3.8567  4.3015  4.3596  4.3596 ยฑ1.07%  135  fastest + ยท wasm-64  213.71  4.3320  5.3301  4.6793  4.8425  5.3176  5.3301  5.3301 ยฑ1.18%  107 + โœ“ bench/gray.bench.tsx > gray 1306ms + name  hz  min  max  mean  p75  p99  p995  p999  rme samples + ยท js 44.7290 22.0049 22.7500 22.3569 22.4467 22.7500 22.7500 22.7500 ยฑ0.30%  23 + ยท wasm  114.37  8.3838  9.4932  8.7436  8.8762  9.4932  9.4932  9.4932 ยฑ0.79%  58  fastest + โœ“ bench/fib.bench.tsx > fib 1238ms + name  hz  min  max  mean  p75  p99  p995  p999  rme samples + ยท js 73,454.37 0.0127 0.2051 0.0136 0.0134 0.0196 0.0252 0.0646 ยฑ0.25%  36728 + ยท wasm 91,504.04 0.0103 0.1469 0.0109 0.0108 0.0156 0.0203 0.0536 ยฑ0.22%  45753  fastest + + + BENCH  Summary + + wasm - bench/fib.bench.tsx > fib + 1.25x faster than js + + wasm - bench/gray.bench.tsx > gray + 2.56x faster than js + + wasm-simd - bench/invert.bench.tsx > gray + 1.26x faster than wasm-64 + 2.03x faster than wasm + 5.56x faster than js \ No newline at end of file diff --git a/assets/win11.min.ans b/assets/win11.min.ans new file mode 100644 index 0000000..721811f --- /dev/null +++ b/assets/win11.min.ans @@ -0,0 +1,22 @@ + Ace@win +################ ################ ------- +################ ################ OS: Windows 11 x86_64 +################ ################ Host: ASUS +################ ################ Kernel: 10.0.26100 +################ ################ Uptime: 4 days, 1 hour, 35 mins +################ ################ Packages: 155 (pacman) +################ ################ Shell: fish 3.7.1 + Display(Generic PnP Monitor): 3840x2160 @ 144Hz (as 2560x1440) * +################ ################ Display(Generic PnP Monitor): 3840x2160 @ 144Hz (as 2560x1440) +################ ################ DE: Fluent +################ ################ WM: Explorer +################ ################ WM Theme: Custom +################ ################ Terminal: Windows Terminal +################ ################ Disk(C): 397.9 GiB / 930.7 GiB (43%) +################ ################ Disk(D): 105.8 GiB / 1.8 TiB ( 6%) + CPU: Intel(R) Core(TM) i7-14700KF @ 3.42GHz + GPU: NVIDIA GeForce RTX 4080 + Memory: 11.3 GiB / 31.8 GiB + +         +         \ No newline at end of file