vtcode_core/ui/
markdown.rs1use crate::config::loader::SyntaxHighlightingConfig;
2use crate::ui::theme::{self, ThemeStyles};
3use anstyle::Style;
4
5#[cfg(feature = "tui")]
7pub use vtcode_tui::ui::markdown::{
8 HighlightedSegment, MarkdownLine, MarkdownSegment, RenderMarkdownOptions,
9 highlight_code_to_ansi, highlight_code_to_segments, highlight_line_for_diff,
10};
11
12#[cfg(not(feature = "tui"))]
14pub use vtcode_commons::ui_protocol::{
15 HighlightedSegment, MarkdownLine, MarkdownSegment, RenderMarkdownOptions,
16};
17
18#[cfg(not(feature = "tui"))]
19pub fn highlight_code_to_ansi(code: &str, _language: Option<&str>, _theme: &str) -> String {
20 code.to_string()
21}
22
23#[cfg(not(feature = "tui"))]
24pub fn highlight_code_to_segments(
25 code: &str,
26 _language: Option<&str>,
27 _theme: &str,
28) -> Vec<HighlightedSegment> {
29 vec![HighlightedSegment {
30 style: Style::default(),
31 text: code.to_string(),
32 }]
33}
34
35#[cfg(not(feature = "tui"))]
36pub fn highlight_line_for_diff(
37 line: &str,
38 _language: Option<&str>,
39) -> Option<Vec<(Style, String)>> {
40 Some(vec![(Style::default(), line.to_string())])
41}
42
43pub fn render_markdown_to_lines(
46 source: &str,
47 base_style: Style,
48 theme_styles: &ThemeStyles,
49 highlight_config: Option<&SyntaxHighlightingConfig>,
50) -> Vec<MarkdownLine> {
51 render_markdown_to_lines_with_options(
52 source,
53 base_style,
54 theme_styles,
55 highlight_config,
56 RenderMarkdownOptions::default(),
57 )
58}
59
60#[cfg(feature = "tui")]
61pub fn render_markdown_to_lines_with_options(
62 source: &str,
63 base_style: Style,
64 theme_styles: &ThemeStyles,
65 highlight_config: Option<&SyntaxHighlightingConfig>,
66 render_options: RenderMarkdownOptions,
67) -> Vec<MarkdownLine> {
68 let tui_theme_styles = crate::ui::tui_compat::tui_theme_styles_from_core(theme_styles);
69 let tui_highlight_cfg = highlight_config.map(|cfg| vtcode_tui::TuiSyntaxHighlightingConfig {
70 enabled: cfg.enabled,
71 theme: cfg.theme.clone(),
72 cache_themes: cfg.cache_themes,
73 max_file_size_mb: cfg.max_file_size_mb,
74 enabled_languages: cfg.enabled_languages.clone(),
75 highlight_timeout_ms: cfg.highlight_timeout_ms,
76 });
77 vtcode_tui::ui::markdown::render_markdown_to_lines_with_options(
78 source,
79 base_style,
80 &tui_theme_styles,
81 tui_highlight_cfg.as_ref(),
82 render_options,
83 )
84}
85
86#[cfg(not(feature = "tui"))]
87pub fn render_markdown_to_lines_with_options(
88 source: &str,
89 base_style: Style,
90 _theme_styles: &ThemeStyles,
91 _highlight_config: Option<&SyntaxHighlightingConfig>,
92 _render_options: RenderMarkdownOptions,
93) -> Vec<MarkdownLine> {
94 let mut lines: Vec<MarkdownLine> = source
95 .lines()
96 .map(|line| MarkdownLine {
97 segments: if line.is_empty() {
98 Vec::new()
99 } else {
100 vec![MarkdownSegment {
101 style: base_style,
102 text: line.to_string(),
103 link_target: None,
104 }]
105 },
106 })
107 .collect();
108 if lines.is_empty() {
109 lines.push(MarkdownLine::default());
110 }
111 lines
112}
113
114pub fn render_markdown(source: &str) -> Vec<MarkdownLine> {
115 let styles = theme::active_styles();
116 render_markdown_to_lines(source, Style::default(), &styles, None)
117}
118
119#[cfg(test)]
120mod tests {
121 use super::*;
122
123 #[test]
124 fn facade_renders_markdown() {
125 let lines = render_markdown("# Heading");
126 assert!(!lines.is_empty());
127 }
128}