summaryrefslogtreecommitdiffstats
path: root/src/lib.rs
blob: b84db96f3c32d607639b39b5440f3c2b4eecae93 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
use std::fs::File;
use std::io::prelude::*;

use structopt::StructOpt;

#[derive(StructOpt, Debug)]
#[structopt(name = "mktoc")]
struct Cli {
    #[structopt()]
    file: String,

    #[structopt(long, short)]
    write: bool,
}

const COMMENT_BEGIN: &str = "<!-- BEGIN mktoc -->";
const COMMENT_END: &str = "<!-- END mktoc -->";

fn read_file(file_path: String) -> Result<String, ::std::io::Error> {
    let mut file = File::open(file_path)?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;

    Ok(contents)
}

fn generate_toc(original_content: String) -> String {
    // @TODO: This RegEx creates weird outputs if the headline contains additional markdown, like images
    let re = regex::Regex::new(r"((#{1,6}\s))((.*))").unwrap();
    let mut new_toc = String::from(COMMENT_BEGIN);
    // let caps = re.captures(content.as_str());
    for caps in re.captures_iter(original_content.as_str()) {
        let level: usize = caps.get(2).unwrap().as_str().chars().count() - 1;
        let text = caps.get(3).unwrap().as_str();
        // @TODO: Use real URL encoding
        let link = text.replace(" ", "-").to_ascii_lowercase();
        // let spaces = " ".repeat(level -1);
        let spaces = match level {
            1 | 2 => String::from(""),
            3 => String::from("  "),
            4 => String::from("    "),
            5 => String::from("      "),
            6 => String::from("        "),
            _ => String::from(""),
        };

        new_toc = format!(
            "{old}\n{spaces}- [{text}](#{link})",
            old = new_toc,
            spaces = spaces,
            text = text,
            link = link
        );
    }

    new_toc = format!("{}\n{}", new_toc, COMMENT_END);

    return new_toc;
}

pub fn make_toc(file_path_in: String) -> Result<String, ::std::io::Error> {
    let content = read_file(file_path_in)?;
    let new_toc = generate_toc(content.to_owned());
    let re_toc = regex::Regex::new(r"(?ms)^(<!-- BEGIN mktoc).*(END mktoc -->)").unwrap();
    let res: String = re_toc
        .replace_all(content.as_str(), new_toc.as_str())
        .into_owned();

    Ok(res)
}