2021-02-20 23:35:45 +03:00
|
|
|
use serde_yaml::Result;
|
|
|
|
|
|
|
|
/// YAML front matter from an Obsidian note.
|
|
|
|
///
|
2024-08-03 14:38:23 +03:00
|
|
|
/// This is essentially an alias of [`serde_yaml::Mapping`] so all the methods available on that
|
|
|
|
/// type are available with `Frontmatter` as well.
|
2021-02-20 23:35:45 +03:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// # use obsidian_export::Frontmatter;
|
|
|
|
/// use serde_yaml::Value;
|
|
|
|
///
|
|
|
|
/// let mut frontmatter = Frontmatter::new();
|
|
|
|
/// let key = Value::String("foo".to_string());
|
|
|
|
///
|
2024-08-03 14:38:23 +03:00
|
|
|
/// frontmatter.insert(key.clone(), Value::String("bar".to_string()));
|
2021-02-20 23:35:45 +03:00
|
|
|
///
|
|
|
|
/// assert_eq!(
|
|
|
|
/// frontmatter.get(&key),
|
|
|
|
/// Some(&Value::String("bar".to_string())),
|
|
|
|
/// )
|
|
|
|
/// ```
|
|
|
|
pub type Frontmatter = serde_yaml::Mapping;
|
|
|
|
|
2024-08-02 19:46:17 +03:00
|
|
|
// Would be nice to rename this to just from_str, but that would be a breaking change.
|
|
|
|
#[allow(clippy::module_name_repetitions)]
|
2021-02-20 23:35:45 +03:00
|
|
|
pub fn frontmatter_from_str(mut s: &str) -> Result<Frontmatter> {
|
|
|
|
if s.is_empty() {
|
|
|
|
s = "{}";
|
|
|
|
}
|
|
|
|
let frontmatter: Frontmatter = serde_yaml::from_str(s)?;
|
|
|
|
Ok(frontmatter)
|
|
|
|
}
|
|
|
|
|
2024-08-02 19:46:17 +03:00
|
|
|
// Would be nice to rename this to just to_str, but that would be a breaking change.
|
|
|
|
#[allow(clippy::module_name_repetitions)]
|
|
|
|
pub fn frontmatter_to_str(frontmatter: &Frontmatter) -> Result<String> {
|
2021-02-20 23:35:45 +03:00
|
|
|
if frontmatter.is_empty() {
|
2024-08-02 19:46:17 +03:00
|
|
|
return Ok("---\n---\n".to_owned());
|
2021-02-20 23:35:45 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
let mut buffer = String::new();
|
2022-11-05 16:25:33 +03:00
|
|
|
buffer.push_str("---\n");
|
2021-02-20 23:35:45 +03:00
|
|
|
buffer.push_str(&serde_yaml::to_string(&frontmatter)?);
|
|
|
|
buffer.push_str("---\n");
|
|
|
|
Ok(buffer)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Available strategies for the inclusion of frontmatter in notes.
|
2024-08-02 19:46:17 +03:00
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
|
|
// Would be nice to rename this to just Strategy, but that would be a breaking change.
|
|
|
|
#[allow(clippy::module_name_repetitions)]
|
|
|
|
#[non_exhaustive]
|
2021-02-20 23:35:45 +03:00
|
|
|
pub enum FrontmatterStrategy {
|
|
|
|
/// Copy frontmatter when a note has frontmatter defined.
|
|
|
|
Auto,
|
|
|
|
/// Always add frontmatter header, including empty frontmatter when none was originally
|
|
|
|
/// specified.
|
|
|
|
Always,
|
|
|
|
/// Never add any frontmatter to notes.
|
|
|
|
Never,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use pretty_assertions::assert_eq;
|
|
|
|
use serde_yaml::Value;
|
|
|
|
|
2024-08-03 14:38:23 +03:00
|
|
|
use super::*;
|
|
|
|
|
2021-02-20 23:35:45 +03:00
|
|
|
#[test]
|
|
|
|
fn empty_string_should_yield_empty_frontmatter() {
|
2024-08-02 19:46:17 +03:00
|
|
|
assert_eq!(frontmatter_from_str("").unwrap(), Frontmatter::new());
|
2021-02-20 23:35:45 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn empty_frontmatter_to_str() {
|
|
|
|
let frontmatter = Frontmatter::new();
|
|
|
|
assert_eq!(
|
2024-08-02 19:46:17 +03:00
|
|
|
frontmatter_to_str(&frontmatter).unwrap(),
|
2021-02-20 23:35:45 +03:00
|
|
|
format!("---\n---\n")
|
2024-08-02 19:46:17 +03:00
|
|
|
);
|
2021-02-20 23:35:45 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn nonempty_frontmatter_to_str() {
|
|
|
|
let mut frontmatter = Frontmatter::new();
|
2024-08-03 14:17:45 +03:00
|
|
|
frontmatter.insert(Value::String("foo".into()), Value::String("bar".into()));
|
2021-02-20 23:35:45 +03:00
|
|
|
assert_eq!(
|
2024-08-02 19:46:17 +03:00
|
|
|
frontmatter_to_str(&frontmatter).unwrap(),
|
2021-02-20 23:35:45 +03:00
|
|
|
format!("---\nfoo: bar\n---\n")
|
2024-08-02 19:46:17 +03:00
|
|
|
);
|
2021-02-20 23:35:45 +03:00
|
|
|
}
|
|
|
|
}
|