use super::router::Pattern;
use super::ThemeError;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
#[serde(default)]
pub struct PageSettings {
pub url: String,
pub layout: String,
pub title: String,
pub description: String,
pub meta_title: String,
pub meta_description: String,
pub meta_image: String,
pub meta_type: String,
pub meta_robots: String,
pub hidden: bool,
}
impl PageSettings {
pub fn from_value(value: &serde_json::Value) -> Result<Self, ThemeError> {
serde_json::from_value(value.clone())
.map_err(|e| ThemeError::Page(format!("the settings do not fit a page: {e}")))
}
pub fn pattern(&self) -> Result<Pattern, ThemeError> {
if self.url.trim().is_empty() {
return Err(ThemeError::Page("a page needs a url".into()));
}
Pattern::parse(self.url.trim()).map_err(|e| ThemeError::Page(format!("url: {e}")))
}
pub fn layout_path(&self) -> Option<String> {
let name = self.layout.trim();
if name.is_empty() {
None
} else if name.contains('.') {
Some(name.to_string())
} else {
Some(format!("{name}.htm"))
}
}
pub fn check(&self, layouts: &[String]) -> Result<(), ThemeError> {
self.pattern()?;
if let Some(path) = self.layout_path() {
if !layouts.contains(&path) {
return Err(ThemeError::Page(format!(
"no layout {path:?} in this theme"
)));
}
}
Ok(())
}
}
pub fn page_name(path: &str) -> &str {
path.strip_suffix(".htm")
.or_else(|| path.strip_suffix(".html"))
.unwrap_or(path)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn settings_check_the_url_and_the_layout() {
let s = PageSettings::from_value(&serde_json::json!({"url": "/", "layout": "default"}))
.unwrap();
assert!(s.check(&["default.htm".to_string()]).is_ok());
assert!(s.check(&[]).is_err());
let s = PageSettings::from_value(&serde_json::json!({"url": "/blog/:a*/:b*"})).unwrap();
assert!(s.check(&[]).is_err());
let s = PageSettings::from_value(&serde_json::json!({"title": "x"})).unwrap();
assert!(s.check(&[]).is_err(), "a url is required");
let s =
PageSettings::from_value(&serde_json::json!({"url": "/", "layout": "site/base.htm"}))
.unwrap();
assert_eq!(s.layout_path().as_deref(), Some("site/base.htm"));
assert_eq!(page_name("blog/post.htm"), "blog/post");
assert_eq!(page_name("home.html"), "home");
assert_eq!(page_name("raw"), "raw");
}
}