synpad 0.1.0

A full-featured Matrix chat client built with Dioxus
use linkify::{LinkFinder, LinkKind};

/// Find all URLs in a text string.
pub fn find_links(text: &str) -> Vec<LinkMatch> {
    let mut finder = LinkFinder::new();
    finder.kinds(&[LinkKind::Url, LinkKind::Email]);

    finder
        .links(text)
        .map(|link| LinkMatch {
            start: link.start(),
            end: link.end(),
            url: link.as_str().to_string(),
            kind: match link.kind() {
                LinkKind::Url => LinkKindSimple::Url,
                LinkKind::Email => LinkKindSimple::Email,
                _ => LinkKindSimple::Url,
            },
        })
        .collect()
}

/// A matched link in text.
#[derive(Clone, Debug)]
pub struct LinkMatch {
    pub start: usize,
    pub end: usize,
    pub url: String,
    pub kind: LinkKindSimple,
}

/// Simplified link type.
#[derive(Clone, Debug, PartialEq)]
pub enum LinkKindSimple {
    Url,
    Email,
}

/// Convert plain text to HTML with auto-linked URLs.
pub fn linkify_text(text: &str) -> String {
    let links = find_links(text);
    if links.is_empty() {
        return html_escape(text);
    }

    let mut result = String::new();
    let mut last_end = 0;

    for link in &links {
        // Add text before the link
        result.push_str(&html_escape(&text[last_end..link.start]));

        // Add the link
        let href = match link.kind {
            LinkKindSimple::Url => link.url.clone(),
            LinkKindSimple::Email => format!("mailto:{}", link.url),
        };

        result.push_str(&format!(
            r#"<a href="{}" target="_blank" rel="noopener noreferrer">{}</a>"#,
            html_escape(&href),
            html_escape(&link.url)
        ));

        last_end = link.end;
    }

    // Add remaining text
    result.push_str(&html_escape(&text[last_end..]));

    result
}

/// Simple HTML escaping.
fn html_escape(text: &str) -> String {
    text.replace('&', "&amp;")
        .replace('<', "&lt;")
        .replace('>', "&gt;")
        .replace('"', "&quot;")
        .replace('\'', "&#39;")
}