Skip to content

Commit fa2ca73

Browse files
committed
Use ansi_to_html to style
There's a fun wrinkle here: jj uses crossterm, which always outputs the 256-color ANSI codes, even if they're only the base 16 colors. As such, ansi_to_html doesn't use the semantic names for the css output, instead outputting the color as RGB directly. This would make it difficult to style the output. So I have to pre-process it slightly.
1 parent 486cc99 commit fa2ca73

File tree

1 file changed

+31
-9
lines changed

1 file changed

+31
-9
lines changed

mdbook-trycmd/src/main.rs

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ impl Cache {
5656

5757
map.entry(key.to_string())
5858
.or_insert_with(|| {
59-
eprintln!("===rendering {key}");
6059
let contents = fs::read_to_string(key).unwrap();
6160
let contents: String = contents
6261
.lines()
@@ -68,11 +67,9 @@ impl Cache {
6867

6968
let dir = TempDir::new().unwrap();
7069

71-
// we use git init here because we want .gitignore, and then rm .git
72-
7370
for command in contents.lines() {
7471
// getting real hard-coded with it. we want to set this to never for
75-
// reproducibility in trycmd, but we also want it to be on here becuase
72+
// reproducibility in trycmd, but we also want it to be on here because
7673
// that's the whole dang point!
7774
let command = if command == "$ jj config set --repo ui.color never" {
7875
" jj config set --repo ui.color always"
@@ -91,10 +88,17 @@ impl Cache {
9188
.output()
9289
.unwrap();
9390

94-
let render = |s| ansi_to_html::convert(&String::from_utf8(s).unwrap()).unwrap();
9591

96-
let stdout = render(output.stdout);
97-
let stderr = render(output.stderr);
92+
let render = |s| {
93+
let input = String::from_utf8(s).unwrap();
94+
let input = replace_colors(input);
95+
ansi_to_html::Converter::new()
96+
.four_bit_var_prefix(Some("jj-".to_string()))
97+
.convert(&input)
98+
};
99+
100+
let stdout = render(output.stdout).expect("stdout failed to render");
101+
let stderr = render(output.stderr).expect("stderr failed to render");
98102

99103
rendered.push('$');
100104
rendered.push_str(command);
@@ -106,14 +110,32 @@ impl Cache {
106110
}
107111
}
108112

109-
eprintln!("===output: {rendered}");
110-
111113
rendered
112114
})
113115
.to_string()
114116
}
115117
}
116118

119+
fn replace_colors(input: String) -> String {
120+
let re = Regex::new(r"\x1b\[38;5;([0-9]+)m").unwrap();
121+
122+
re.replace_all(&input, |caps: &regex::Captures| {
123+
if let Ok(num) = caps[1].parse::<u8>() {
124+
let replacement = match num {
125+
0..=7 => 30 + num, // Standard foreground colors
126+
8..=15 => 90 + (num - 8), // Bright foreground colors
127+
code => {
128+
eprintln!("non-16 color found: {code}");
129+
return caps[0].to_string(); // Keep unchanged if out of range
130+
},
131+
};
132+
format!("\x1b[{}m", replacement)
133+
} else {
134+
caps[0].to_string()
135+
}
136+
}).to_string()
137+
}
138+
117139
fn run_examples(content: &str) -> Result<String> {
118140
let mut buf = content.to_string();
119141
let regex = Regex::new(r#"\{\{#trycmdinclude ([\w\/.\-]+):(\d+)(?::(\d+))?\}\}"#).unwrap();

0 commit comments

Comments
 (0)