diff --git a/src/site.rs b/src/site.rs index 46323ed..4aa1974 100644 --- a/src/site.rs +++ b/src/site.rs @@ -59,6 +59,7 @@ impl Site { /// /// Will return an error if serialization fails, the user does not have write permissions for /// the directory, or any other IO errors occur while writing out the config. + #[allow(clippy::too_many_lines)] pub fn write(&mut self, site_dir: impl AsRef) -> Result<(), SiteError> { let site_dir = site_dir.as_ref(); // Setup logging @@ -80,6 +81,7 @@ impl Site { debug!(?self.config, "Writing out the config"); let config_path = site_dir.join("config.dhall"); let serialized_config = serde_dhall::serialize(&self.config) + .static_type_annotation() .to_string() .context(ConfigReifySnafu)?; let mut config_file = @@ -196,6 +198,7 @@ impl Site { let config_path = site_dir.join("config.dhall"); debug!(?config_path, "Reading main site configuration file"); let config: Config = serde_dhall::from_file(&config_path) + .static_type_annotation() .parse() .context(ConfigReadSnafu { path: &config_path })?; diff --git a/src/site/config.rs b/src/site/config.rs index a8ae595..21e8ef9 100644 --- a/src/site/config.rs +++ b/src/site/config.rs @@ -1,9 +1,10 @@ //! Configuration for a site use serde::{Deserialize, Serialize}; +use serde_dhall::StaticType; /// Description of the domain name and related settings for a site -#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, StaticType)] pub struct Domain { /// The domain name itself pub domain_name: String, @@ -23,7 +24,7 @@ impl Default for Domain { /// Top level configuration for a site /// /// Describes the file located at `site/config.dhall` -#[derive(Serialize, Deserialize, Debug, Default, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Default, PartialEq, Eq, StaticType)] pub struct Config { /// Doman name settings pub domain: Domain, diff --git a/src/site/page.rs b/src/site/page.rs index 352f1f1..60e20ae 100644 --- a/src/site/page.rs +++ b/src/site/page.rs @@ -9,6 +9,7 @@ use std::{ }; use serde::{Deserialize, Serialize}; +use serde_dhall::StaticType; use snafu::{ensure, ResultExt}; use tracing::{debug, info, info_span, warn}; @@ -19,7 +20,7 @@ use super::{ }; /// Representation of the configuration for a page -#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, StaticType)] pub struct PageConfig { /// Title of the page title: String, @@ -95,6 +96,7 @@ impl Page { let config_path = page_dir.join("page.dhall"); debug!(?config_path, ?self.config, "Writing out page config"); let serialized_config = serde_dhall::serialize(&self.config) + .static_type_annotation() .to_string() .context(ConfigReifySnafu)?; let mut config_file = @@ -172,12 +174,12 @@ impl Page { let config_path = dhall_canidates.remove(0); debug!(?config_path, "Reading config"); let real_config_path = page_dir.join(config_path); - let config: PageConfig = - serde_dhall::from_file(&real_config_path) - .parse() - .context(ConfigReadSnafu { - path: &real_config_path, - })?; + let config: PageConfig = serde_dhall::from_file(&real_config_path) + .static_type_annotation() + .parse() + .context(ConfigReadSnafu { + path: &real_config_path, + })?; // Find the djot file let mut djot_canidates = file_names diff --git a/src/site/post.rs b/src/site/post.rs index 3ac7085..5ae18bc 100644 --- a/src/site/post.rs +++ b/src/site/post.rs @@ -2,6 +2,7 @@ use std::{ borrow::Cow, + collections::HashMap, ffi::OsStr, fs::{create_dir_all, read_dir, File}, io::Write, @@ -10,6 +11,7 @@ use std::{ use chrono::{Local, NaiveDate}; use serde::{Deserialize, Serialize}; +use serde_dhall::{SimpleType, StaticType}; use snafu::{ensure, ResultExt}; use tracing::{debug, info, info_span, span, warn, Level}; @@ -44,6 +46,20 @@ impl Default for PostConfig { } } +impl StaticType for PostConfig { + fn static_type() -> serde_dhall::SimpleType { + let mut type_map: HashMap = HashMap::new(); + type_map.insert("title".into(), SimpleType::Text); + // TODO: Find a way to represent a date as strongly typed value instead of stringly typed + type_map.insert("date".into(), SimpleType::Text); + type_map.insert( + "stylesheets".into(), + SimpleType::List(Box::new(SimpleType::Text)), + ); + SimpleType::Record(type_map) + } +} + /// Representation of a post #[derive(Debug, PartialEq, Eq)] pub struct Post { @@ -100,6 +116,7 @@ impl Post { let config_path = post_dir.join("post.dhall"); debug!(?config_path, ?self.config, "Writing out config"); let serialized_config = serde_dhall::serialize(&self.config) + .static_type_annotation() .to_string() .context(ConfigReifySnafu)?; let mut config_file = @@ -177,12 +194,12 @@ impl Post { let config_path = dhall_canidates.remove(0); debug!(?config_path, "Reading config"); let real_config_path = post_dir.join(config_path); - let config: PostConfig = - serde_dhall::from_file(&real_config_path) - .parse() - .context(ConfigReadSnafu { - path: &real_config_path, - })?; + let config: PostConfig = serde_dhall::from_file(&real_config_path) + .static_type_annotation() + .parse() + .context(ConfigReadSnafu { + path: &real_config_path, + })?; // Find the djot file let mut djot_canidates = file_names