robson-core 0.0.2

Rust async agent orchestrator for automated development workflows
Documentation
/// Convert a subset of Markdown to Slack mrkdwn format.
/// - `**text**` → `*text*`
/// - `__text__` → `_text_`
/// - `### heading` / `## heading` / `# heading` → `*heading*`
/// - `` `code` `` stays as `` `code` ``
/// - ` ```lang\n...\n``` ` stays as ` ``` ` blocks (unchanged)
pub fn markdown_to_mrkdwn(text: &str) -> String {
    let mut result = text.to_string();

    // Convert headings: lines starting with #+ space → *text*
    let lines: Vec<String> = result
        .lines()
        .map(|line| {
            if let Some(rest) = line.strip_prefix("### ") {
                format!("*{}*", rest)
            } else if let Some(rest) = line.strip_prefix("## ") {
                format!("*{}*", rest)
            } else if let Some(rest) = line.strip_prefix("# ") {
                format!("*{}*", rest)
            } else {
                line.to_string()
            }
        })
        .collect();

    result = lines.join("\n");

    // Convert **bold** → *bold* (before single * to avoid conflicts)
    result = replace_delimited(&result, "**", "*");

    // Convert __italic__ → _italic_
    result = replace_delimited(&result, "__", "_");

    result
}

/// Replace paired `delim` with `replacement` around inner content.
fn replace_delimited(text: &str, delim: &str, replacement: &str) -> String {
    let mut result = String::with_capacity(text.len());
    let dlen = delim.len();
    let text_len = text.len();
    let mut i = 0;

    while i < text_len {
        // Check if delimiter starts here
        if text[i..].starts_with(delim) {
            // Find closing delimiter after the opening one
            let search_from = i + dlen;
            if let Some(close_offset) = text[search_from..].find(delim) {
                let inner_start = search_from;
                let inner_end = search_from + close_offset;
                let inner = &text[inner_start..inner_end];
                result.push_str(replacement);
                result.push_str(inner);
                result.push_str(replacement);
                i = inner_end + dlen;
                continue;
            }
        }
        // Advance one char (UTF-8 safe)
        let ch_len = text[i..].chars().next().map(|c| c.len_utf8()).unwrap_or(1);
        result.push_str(&text[i..i + ch_len]);
        i += ch_len;
    }

    result
}