pub fn markdown_to_mrkdwn(input: &str) -> String {
let mut output = String::with_capacity(input.len());
let mut chars = input.chars().peekable();
let mut in_code_block = false;
let mut in_inline_code = false;
let mut line_start = true;
while let Some(c) = chars.next() {
if c == '`' && chars.peek() == Some(&'`') {
let next = chars.next(); if chars.peek() == Some(&'`') {
chars.next(); in_code_block = !in_code_block;
output.push_str("```");
continue;
}
output.push('`');
if let Some(n) = next {
output.push(n);
}
continue;
}
if in_code_block {
output.push(c);
line_start = c == '\n';
continue;
}
if c == '`' {
in_inline_code = !in_inline_code;
output.push(c);
continue;
}
if in_inline_code {
output.push(c);
continue;
}
if line_start && c == '#' {
while chars.peek() == Some(&'#') {
chars.next();
}
if chars.peek() == Some(&' ') {
chars.next();
}
let mut heading = String::new();
for hc in chars.by_ref() {
if hc == '\n' {
break;
}
heading.push(hc);
}
let heading = heading.trim_end();
output.push_str(&format!("*{}*\n", heading));
line_start = true;
continue;
}
if c == '*' && chars.peek() == Some(&'*') {
chars.next(); output.push('*');
continue;
}
if c == '~' && chars.peek() == Some(&'~') {
chars.next(); output.push('~');
continue;
}
if c == '[' {
let mut text = String::new();
let mut found_close = false;
for lc in chars.by_ref() {
if lc == ']' {
found_close = true;
break;
}
text.push(lc);
}
if found_close && chars.peek() == Some(&'(') {
chars.next(); let mut url = String::new();
for uc in chars.by_ref() {
if uc == ')' {
break;
}
url.push(uc);
}
output.push_str(&format!("<{}|{}>", url, text));
} else {
output.push('[');
output.push_str(&text);
if found_close {
output.push(']');
}
}
continue;
}
line_start = c == '\n';
output.push(c);
}
output
}