ratatui-markdown 0.3.6

Markdown rendering, syntax highlighting, collapsible trees, and rich scroll widgets for ratatui
Documentation
use std::sync::Arc;

use ratatui::{
    style::Style,
    text::{Line, Span},
};

use super::CodeHighlighter;
use crate::constants::list_prefix::{HLINE, ROUNDED_BL, ROUNDED_TL, VLINE};

pub struct HighlightHooks {
    highlighter: Arc<dyn CodeHighlighter>,
    max_width: usize,
    border_color: ratatui::style::Color,
}

impl HighlightHooks {
    pub fn new(highlighter: Arc<dyn CodeHighlighter>, max_width: usize) -> Self {
        Self {
            highlighter,
            max_width,
            border_color: ratatui::style::Color::DarkGray,
        }
    }

    pub fn with_border_color(mut self, color: ratatui::style::Color) -> Self {
        self.border_color = color;
        self
    }
}

#[cfg(feature = "markdown")]
impl crate::markdown::RenderHooks for HighlightHooks {
    fn render_code_block(&self, lang: &str, content: &str) -> Option<Vec<Line<'static>>> {
        let segments = self.highlighter.highlight(lang, content);
        if segments.is_empty() {
            return None;
        }

        let border_style = Style::default().fg(self.border_color);
        let display_lang = if lang.is_empty() { "code" } else { lang };

        let mut lines = Vec::new();

        lines.push(Line::from(Span::styled(
            format!("{ROUNDED_TL}{HLINE} {display_lang}"),
            border_style,
        )));

        let prefix = format!("{VLINE} ");
        let content_width = self.max_width.saturating_sub(2);

        let code_lines = super::segment::segments_to_lines(
            content,
            &segments,
            &prefix,
            border_style,
            content_width,
        );
        lines.extend(code_lines);

        lines.push(Line::from(Span::styled(
            format!("{ROUNDED_BL}{HLINE}"),
            border_style,
        )));

        Some(lines)
    }
}