c6o_obsidian_export/
frontmatter.rs

1use serde_yaml::Result;
2
3/// YAML front matter from an Obsidian note.
4///
5/// This is essentially an alias of [serde_yaml::Mapping] so all the methods available on that type
6/// are available with `Frontmatter` as well.
7///
8/// # Examples
9///
10/// ```
11/// # use obsidian_export::Frontmatter;
12/// use serde_yaml::Value;
13///
14/// let mut frontmatter = Frontmatter::new();
15/// let key = Value::String("foo".to_string());
16///
17/// frontmatter.insert(
18///     key.clone(),
19///     Value::String("bar".to_string()),
20/// );
21///
22/// assert_eq!(
23///     frontmatter.get(&key),
24///     Some(&Value::String("bar".to_string())),
25/// )
26/// ```
27pub type Frontmatter = serde_yaml::Mapping;
28
29pub fn frontmatter_from_str(mut s: &str) -> Result<Frontmatter> {
30    if s.is_empty() {
31        s = "{}";
32    }
33    let frontmatter: Frontmatter = serde_yaml::from_str(s)?;
34    Ok(frontmatter)
35}
36
37pub fn frontmatter_to_str(frontmatter: Frontmatter) -> Result<String> {
38    if frontmatter.is_empty() {
39        return Ok("---\n---\n".to_string());
40    }
41
42    let mut buffer = String::new();
43    buffer.push_str(&serde_yaml::to_string(&frontmatter)?);
44    buffer.push_str("---\n");
45    Ok(buffer)
46}
47
48#[derive(Debug, Clone, Copy)]
49/// Available strategies for the inclusion of frontmatter in notes.
50pub enum FrontmatterStrategy {
51    /// Copy frontmatter when a note has frontmatter defined.
52    Auto,
53    /// Always add frontmatter header, including empty frontmatter when none was originally
54    /// specified.
55    Always,
56    /// Never add any frontmatter to notes.
57    Never,
58}
59
60#[cfg(test)]
61mod tests {
62    use super::*;
63    use pretty_assertions::assert_eq;
64    use serde_yaml::Value;
65
66    #[test]
67    fn empty_string_should_yield_empty_frontmatter() {
68        assert_eq!(frontmatter_from_str("").unwrap(), Frontmatter::new())
69    }
70
71    #[test]
72    fn empty_frontmatter_to_str() {
73        let frontmatter = Frontmatter::new();
74        assert_eq!(
75            frontmatter_to_str(frontmatter).unwrap(),
76            format!("---\n---\n")
77        )
78    }
79
80    #[test]
81    fn nonempty_frontmatter_to_str() {
82        let mut frontmatter = Frontmatter::new();
83        frontmatter.insert(
84            Value::String("foo".to_string()),
85            Value::String("bar".to_string()),
86        );
87        assert_eq!(
88            frontmatter_to_str(frontmatter).unwrap(),
89            format!("---\nfoo: bar\n---\n")
90        )
91    }
92}