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