teensy_cms/
page.rs

1//! Frontmatter de/serialization helpers.
2use serde::de::DeserializeOwned;
3use serde::{Deserialize, Serialize};
4
5/// Trait for a page's frontmatter that loaded from a template.
6pub trait Page: Serialize + DeserializeOwned {
7    /// The page's title it should be displayed in a nav bar or menu.
8    fn title(&self) -> String;
9}
10
11/// A struct that collects all values and makes them available to the page or templates.
12#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
13pub struct DefaultPage {
14    pub title: String,
15    /// All other fields in the frontmatter.
16    #[serde(flatten, skip_serializing_if = "serde_yaml::Mapping::is_empty")]
17    pub extra: serde_yaml::Mapping,
18}
19
20impl Page for DefaultPage {
21    fn title(&self) -> String {
22        self.title.clone()
23    }
24}
25
26#[cfg(test)]
27mod test {
28    use super::*;
29    use serde_yaml::Value;
30
31    // ensures api stability
32    #[test]
33    fn default_page_de_serializes_missing_extra() {
34        let yaml: Value = serde_yaml::from_str("title: Title").unwrap();
35        let parsed: DefaultPage = serde_yaml::from_value(yaml.clone()).unwrap();
36        assert!(parsed.extra.is_empty());
37        let written = serde_yaml::to_value(&parsed).unwrap();
38        assert_eq!(written, yaml);
39    }
40
41    // ensures api stability
42    #[test]
43    fn default_page_de_serializes_extra() {
44        let yaml: Value = serde_yaml::from_str("title: Title\nmoar: stuff").unwrap();
45        let parsed: DefaultPage = serde_yaml::from_value(yaml.clone()).unwrap();
46        assert_eq!(&parsed.extra["moar"], "stuff");
47        let written = serde_yaml::to_value(&parsed).unwrap();
48        assert_eq!(written, yaml);
49    }
50}