onelo_backend/files/
mod.rs

1use crate::context::Result;
2use regex::Regex;
3use std::error::Error;
4use std::fmt;
5use std::fs;
6use std::path::{Path, PathBuf};
7
8#[derive(Debug)]
9struct SplitError(String);
10
11impl fmt::Display for SplitError {
12    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
13        write!(f, "{}", self.0)
14    }
15}
16
17impl Error for SplitError {}
18
19/// Get all markdown files of a path
20pub fn get_markdown_files<P: AsRef<Path>>(path: P) -> Result<Vec<PathBuf>> {
21    let mut paths = vec![];
22
23    for result in fs::read_dir(path)? {
24        let path = result?.path();
25
26        if is_valid_file(&path) {
27            paths.push(path);
28        }
29    }
30
31    Ok(paths)
32}
33
34/// Check if a file is a valid source
35fn is_valid_file(path: &PathBuf) -> bool {
36    if let Some(ext) = path.extension() {
37        return ext == "md";
38    }
39
40    false
41}
42
43/// Get the content of a file as String
44pub fn get_file_content<P: AsRef<Path>>(path: P) -> Result<String> {
45    let file = fs::read_to_string(path)?;
46
47    Ok(file)
48}
49
50/// Take an String with all the file content and split it in metada and data
51pub fn split_content<'c>(content: &'c str) -> Result<(&'c str, &'c str)> {
52    let split_regex =
53        Regex::new(r"^[[:space:]]*\+\+\+(\r?\n(?s).*?(?-s))\+\+\+\r?\n?((?s).*(?-s))$")
54            .expect("Something went wrong when compiling a regular expression.");
55
56    if !split_regex.is_match(content) {
57        return Err(Box::new(SplitError(
58            "Couldn't find metadata. Did you forget to add `+++`?".into(),
59        )));
60    }
61
62    let splitted_content = split_regex.captures(content).ok_or(SplitError(
63        "Something went wrong when splitting the content.".into(),
64    ))?;
65
66    Ok((
67        splitted_content
68            .get(1)
69            .ok_or(SplitError("Couldn't find any metadata".into()))?
70            .as_str()
71            .trim(),
72        splitted_content
73            .get(2)
74            .ok_or(SplitError("Couldn't find any content".into()))?
75            .as_str()
76            .trim(),
77    ))
78}
79
80#[cfg(test)]
81mod tests {
82    use super::*;
83
84    #[test]
85    fn test_get_only_md_files() {
86        let paths = get_markdown_files("test/files");
87        assert_eq!(paths.unwrap().len(), 2);
88    }
89
90    #[test]
91    fn test_get_markdown_file_content() {
92        let file_content = get_file_content("test/files/01.md");
93        let file_content_string = file_content.unwrap();
94
95        let expected = r#"+++
96[metadata]
97id = "01fbd72a-5ad4-4d4d-bc6e-7973e65e02b6"
98+++
99
100# Lorem ipsum
101
102Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc posuere nibh eget tortor rhoncus dictum. Lorem ipsum dolor sit amet, consectetur adipiscing elit."#;
103
104        assert_eq!(file_content_string, expected.to_string());
105    }
106
107    #[test]
108    fn test_split_content_with_metadata() {
109        let content = r#"+++
110[metadata]
111id = "01fbd72a-5ad4-4d4d-bc6e-7973e65e02b6"
112+++
113
114# Lorem ipsum
115
116Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc posuere nibh eget tortor rhoncus dictum. Lorem ipsum dolor sit amet, consectetur adipiscing elit."#;
117        let splitted_content = split_content(content).unwrap();
118
119        assert_eq!(
120            "[metadata]\nid = \"01fbd72a-5ad4-4d4d-bc6e-7973e65e02b6\"",
121            splitted_content.0
122        );
123
124        assert_eq!(
125            "# Lorem ipsum\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc posuere nibh eget tortor rhoncus dictum. Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
126            splitted_content.1
127        );
128    }
129
130    #[test]
131    fn test_split_content_with_empty_metadata() {
132        let content = r#"+++
133+++
134
135# Lorem ipsum
136
137Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc posuere nibh eget tortor rhoncus dictum. Lorem ipsum dolor sit amet, consectetur adipiscing elit."#;
138        assert_eq!(split_content(content).is_ok(), true);
139    }
140
141    #[test]
142    fn test_split_content_without_metadata() {
143        let content = r#"
144# Lorem ipsum
145
146Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc posuere nibh eget tortor rhoncus dictum. Lorem ipsum dolor sit amet, consectetur adipiscing elit."#;
147
148        assert_eq!(split_content(content).is_err(), true);
149    }
150}