1use crate::{
2 ansi::{Color, Ground, NamedColor},
3 lexer::{EmphasisType, TagType, Token},
4};
5
6pub fn tag_to_markup_part(tag: &TagType) -> String {
7 match tag {
8 TagType::Emphasis(e) => match e {
9 EmphasisType::Bold => "bold".to_string(),
10 EmphasisType::Blink => "blink".to_string(),
11 EmphasisType::Dim => "dim".to_string(),
12 EmphasisType::Italic => "italic".to_string(),
13 EmphasisType::Strikethrough => "strikethrough".to_string(),
14 EmphasisType::Underline => "underline".to_string(),
15 EmphasisType::DoubleUnderline => "double-underline".to_string(),
16 EmphasisType::Overline => "overline".to_string(),
17 EmphasisType::Invisible => "invisible".to_string(),
18 EmphasisType::Reverse => "reverse".to_string(),
19 EmphasisType::RapidBlink => "rapid-blink".to_string(),
20 },
21 TagType::Color { color, ground } => {
22 let prepend = match ground {
23 Ground::Background => "bg:",
24 _ => "",
25 };
26 match color {
27 Color::Ansi256(a) => format!("{prepend}ansi({a})"),
28 Color::Named(n) => {
29 let name = match n {
30 NamedColor::Black => "black",
31 NamedColor::Red => "red",
32 NamedColor::Green => "green",
33 NamedColor::Yellow => "yellow",
34 NamedColor::Blue => "blue",
35 NamedColor::Magenta => "magenta",
36 NamedColor::Cyan => "cyan",
37 NamedColor::White => "white",
38 NamedColor::BrightBlack => "bright-black",
39 NamedColor::BrightRed => "bright-red",
40 NamedColor::BrightGreen => "bright-green",
41 NamedColor::BrightYellow => "bright-yellow",
42 NamedColor::BrightBlue => "bright-blue",
43 NamedColor::BrightMagenta => "bright-magenta",
44 NamedColor::BrightCyan => "bright-cyan",
45 NamedColor::BrightWhite => "bright-white",
46 };
47 format!("{prepend}{name}")
48 }
49 Color::Rgb(r, g, b) => format!("{prepend}rgb({r},{g},{b})"),
50 }
51 }
52 TagType::ResetAll => "/".to_string(),
53 TagType::ResetOne(inner) => format!("/{}", tag_to_markup_part(inner)),
54 TagType::Prefix(_) => String::new(),
55 }
56}
57
58pub fn tokens_to_markup(tokens: &[Token]) -> String {
59 let mut result = String::new();
60 let mut i = 0;
61
62 while i < tokens.len() {
63 match &tokens[i] {
64 Token::Text(s) => {
65 result.push_str(s);
66 i += 1;
67 }
68 Token::Tag(_) => {
69 let mut parts = Vec::new();
70 while i < tokens.len() {
71 if let Token::Tag(tag) = &tokens[i] {
72 parts.push(tag_to_markup_part(tag));
73 i += 1;
74 } else {
75 break;
76 }
77 }
78 result.push('[');
79 result.push_str(&parts.join(" "));
80 result.push(']');
81 }
82 }
83 }
84
85 result
86}