1use futures::FutureExt;
2use js_sys::Promise;
3use wasm_bindgen_futures::future_to_promise;
4
5use super::*;
6
7#[wasm_bindgen]
8pub fn highlight(input: String) -> Promise {
9 future_to_promise(highlight_impl(input).map(|s| Ok(JsValue::from_str(&s))))
10}
11
12pub async fn highlight_impl(input: String) -> String {
13 let (global_offset, shapes) = {
14 let engine_guard = read_engine_state().await;
15 let mut working_set = StateWorkingSet::new(&engine_guard);
16 let offset = working_set.next_span_start();
17 let block = parse(&mut working_set, None, input.as_bytes(), false);
18 (offset, flatten_block(&working_set, &block))
19 };
20
21 let mut output = String::new();
22 let mut last_end = 0;
23
24 for (span, shape) in shapes {
25 // Adjust global span to local byte indices
26 let local_start = span.start.saturating_sub(global_offset);
27 let local_end = span.end.saturating_sub(global_offset);
28
29 if local_start >= input.len() {
30 continue;
31 }
32 let safe_end = std::cmp::min(local_end, input.len());
33
34 if local_start > last_end {
35 output.push_str(&input[last_end..local_start]);
36 }
37
38 let start_index = std::cmp::max(local_start, last_end);
39 if start_index >= safe_end {
40 continue;
41 }
42
43 // Colors corresponding to standard Nushell/Ansi map
44 let color = match shape {
45 FlatShape::Pipe | FlatShape::Redirection => "\x1b[35m", // Magenta
46 FlatShape::Bool | FlatShape::Int | FlatShape::Float => "\x1b[35;1m", // Light Magenta (Numbers/Bool)
47 FlatShape::External(_) | FlatShape::InternalCall(_) | FlatShape::Keyword => {
48 "\x1b[32;1m"
49 } // Green Bold
50 FlatShape::String | FlatShape::StringInterpolation | FlatShape::RawString => "\x1b[36m", // Cyan
51 FlatShape::Variable(_) | FlatShape::Flag => "\x1b[34m", // Blue
52 FlatShape::Garbage => "\x1b[31;1m\x1b[47m", // Red on White
53 FlatShape::Signature => "\x1b[33;1m", // Yellow Bold
54 // Closures, blocks, punctuation often fall here
55 FlatShape::Block => "\x1b[37m", // White
56 FlatShape::Closure => "\x1b[36;1m", // Light Cyan
57 _ => "\x1b[0m",
58 };
59
60 output.push_str(color);
61 output.push_str(&input[start_index..safe_end]);
62 output.push_str("\x1b[0m");
63
64 last_end = safe_end;
65 }
66
67 if last_end < input.len() {
68 output.push_str(&input[last_end..]);
69 }
70
71 output
72}