leaf-markdown-viewer 1.26.2

Terminal Markdown previewer with a GUI-like experience
const FRONTMATTER_VERTICAL_THRESHOLD: usize = 5;

pub(super) fn extract_frontmatter(src: &str) -> (&str, Option<Vec<(String, String)>>) {
    let Some(rest) = src.strip_prefix("---\n") else {
        return (src, None);
    };

    let mut offset = 4usize;
    for line in rest.split_inclusive('\n') {
        if line == "---\n" || line == "...\n" || line == "---" || line == "..." {
            let fm_block = &src[4..offset];
            let content = &src[offset + line.len()..];
            let pairs = parse_pairs(fm_block);
            if pairs.is_empty() {
                return (content, None);
            }
            return (content, Some(pairs));
        }
        offset += line.len();
    }

    (src, None)
}

pub(super) fn is_vertical(pairs: &[(String, String)]) -> bool {
    pairs.len() >= FRONTMATTER_VERTICAL_THRESHOLD
}

fn parse_pairs(block: &str) -> Vec<(String, String)> {
    let mut pairs: Vec<(String, String)> = Vec::new();
    let lines: Vec<&str> = block.lines().collect();
    let mut i = 0;

    while i < lines.len() {
        let trimmed = lines[i].trim();
        if trimmed.is_empty() || trimmed.starts_with('#') {
            i += 1;
            continue;
        }

        let Some(colon_pos) = trimmed.find(':') else {
            i += 1;
            continue;
        };

        let key = trimmed[..colon_pos].trim().to_string();
        let raw_value = trimmed[colon_pos + 1..].trim();

        if key.is_empty() {
            i += 1;
            continue;
        }

        if raw_value == ">-" || raw_value == ">" || raw_value == "|" || raw_value == "|-" {
            let mut parts: Vec<&str> = Vec::new();
            i += 1;
            while i < lines.len() && is_indented(lines[i]) {
                let part = lines[i].trim();
                if !part.is_empty() {
                    parts.push(part);
                }
                i += 1;
            }
            pairs.push((key, parts.join(" ")));
        } else if raw_value.is_empty() {
            let mut items: Vec<&str> = Vec::new();
            i += 1;
            while i < lines.len() && is_indented(lines[i]) {
                let part = lines[i].trim();
                if let Some(item) = part.strip_prefix("- ") {
                    items.push(item.trim());
                } else if !part.is_empty() {
                    items.push(part);
                }
                i += 1;
            }
            if items.is_empty() {
                pairs.push((key, String::new()));
            } else {
                pairs.push((key, items.join(", ")));
            }
        } else {
            pairs.push((key, strip_quotes(raw_value).to_string()));
            i += 1;
        }
    }

    pairs
}

fn is_indented(line: &str) -> bool {
    line.starts_with(' ') || line.starts_with('\t')
}

fn strip_quotes(s: &str) -> &str {
    if s.len() >= 2
        && ((s.starts_with('"') && s.ends_with('"')) || (s.starts_with('\'') && s.ends_with('\'')))
    {
        return &s[1..s.len() - 1];
    }
    s
}