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