telekinesis 0.3.6

AI coding agent TUI — rx4 harness + crepuscularity-tui, pi-first UX
use ansi_to_tui::IntoText;
use crepuscularity_tui::ratatui::text::{Line, Text};
use glamour::{Renderer, Style};

pub fn render(markdown: &str, width: usize) -> Vec<Line<'static>> {
    let mut styles = Style::TokyoNight.config();
    styles.document.margin = Some(0);
    styles.document.style.block_prefix.clear();
    styles.document.style.block_suffix.clear();
    let output = Renderer::new()
        .with_style_config(styles)
        .with_word_wrap(width.max(1))
        .with_preserved_newlines(true)
        .render(markdown);

    output
        .into_text()
        .unwrap_or_else(|_| Text::raw(output))
        .lines
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn retains_full_multiline_content() {
        let lines = render(
            "# Status\n\nFirst paragraph survives.\n\n- alpha\n- omega\n\nFinal line survives.",
            80,
        );
        let content = lines
            .iter()
            .map(Line::to_string)
            .collect::<Vec<_>>()
            .join("\n");

        assert!(content.contains("Status"));
        assert!(content.contains("First paragraph survives."));
        assert!(content.contains("alpha"));
        assert!(content.contains("omega"));
        assert!(content.contains("Final line survives."));
    }

    #[test]
    fn styles_and_wraps_markdown() {
        let lines = render(
            "This is **important** and deliberately long enough to wrap across several terminal lines.",
            24,
        );

        assert!(lines.len() > 1);
        assert!(lines
            .iter()
            .flat_map(|line| &line.spans)
            .any(|span| span.style.fg.is_some() || !span.style.add_modifier.is_empty()));
    }
}