use crate::collections::Collection;
use crate::content::Site;
use regex::Regex;
use std::sync::LazyLock;
static RECENT_DIRECTIVE: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"\{\{recent\s+(\w+)\s+(\d+)\}\}").unwrap());
pub fn process_directives(content: &str, site: &Site) -> String {
let mut result = content.to_string();
result = RECENT_DIRECTIVE
.replace_all(&result, |caps: ®ex::Captures| {
let collection_name = &caps[1];
let count: usize = caps[2].parse().unwrap_or(5);
let collection = match collection_name {
"blog" => Collection::Blog,
"notes" => Collection::Notes,
"snippets" => Collection::Snippets,
"talks" => Collection::Talks,
"projects" => Collection::Projects,
"recipes" => Collection::Recipes,
_ => return format!("<!-- Unknown collection: {} -->", collection_name),
};
generate_recent_list(site, collection, count)
})
.to_string();
result
}
fn generate_recent_list(site: &Site, collection: Collection, count: usize) -> String {
let pages = site.recent_pages(collection, count);
if pages.is_empty() {
return String::new();
}
let mut html = String::from("<ul class=\"recent-list\">\n");
for page in pages {
let date_str = page
.date
.map(|d| d.format("%Y-%m-%d").to_string())
.unwrap_or_default();
html.push_str(&format!(
" <li><a href=\"{}\">{}</a>",
html_escape::encode_double_quoted_attribute(&page.url),
html_escape::encode_text(&page.title)
));
if !date_str.is_empty() {
html.push_str(&format!(
" <time datetime=\"{}\">{}</time>",
date_str, date_str
));
}
html.push_str("</li>\n");
}
html.push_str("</ul>");
html
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_directive_regex() {
let content = "{{recent blog 5}}";
assert!(RECENT_DIRECTIVE.is_match(content));
let caps = RECENT_DIRECTIVE.captures(content).unwrap();
assert_eq!(&caps[1], "blog");
assert_eq!(&caps[2], "5");
}
#[test]
fn test_process_unknown_collection() {
let site = Site::new();
let result = process_directives("{{recent unknown 3}}", &site);
assert!(result.contains("Unknown collection"));
}
}