use crate::yaml::{Mapping, Value};
pub const REQUIRED_FRONTMATTER_KEYS: [&str; 4] = ["type", "title", "description", "timestamp"];
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Frontmatter {
map: Mapping,
}
impl Frontmatter {
pub fn new() -> Self {
Frontmatter {
map: Mapping::new(),
}
}
pub fn from_mapping(map: Mapping) -> Self {
Frontmatter { map }
}
pub fn as_mapping(&self) -> &Mapping {
&self.map
}
pub fn as_mapping_mut(&mut self) -> &mut Mapping {
&mut self.map
}
pub fn into_mapping(self) -> Mapping {
self.map
}
pub fn is_empty(&self) -> bool {
self.map.is_empty()
}
pub fn get(&self, key: &str) -> Option<&Value> {
self.map.get(key)
}
pub fn set(&mut self, key: impl Into<String>, value: Value) {
self.map.insert(key, value);
}
pub fn type_(&self) -> Option<String> {
self.map.get("type").and_then(Value::as_display_string)
}
pub fn title(&self) -> Option<String> {
self.map.get("title").and_then(Value::as_display_string)
}
pub fn description(&self) -> Option<String> {
self.map.get("description").and_then(Value::as_display_string)
}
pub fn resource(&self) -> Option<String> {
self.map.get("resource").and_then(Value::as_display_string)
}
pub fn timestamp(&self) -> Option<String> {
self.map.get("timestamp").and_then(Value::as_display_string)
}
pub fn tags(&self) -> Vec<String> {
match self.map.get("tags") {
Some(Value::Sequence(items)) => items
.iter()
.filter_map(Value::as_display_string)
.collect(),
_ => Vec::new(),
}
}
pub fn extension_keys(&self) -> Vec<&str> {
const KNOWN: [&str; 6] = ["type", "title", "description", "resource", "tags", "timestamp"];
self.map
.keys()
.filter(|k| !KNOWN.contains(k))
.collect()
}
}
impl From<Mapping> for Frontmatter {
fn from(map: Mapping) -> Self {
Frontmatter { map }
}
}