diff --git a/src/lib.rs b/src/lib.rs index 5e36eca..0de851e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,6 +23,7 @@ use std::ffi::OsStr; use git2::{Repository, Signature, Commit}; +use rocket::form::validate::Contains; use tera::Tera; use toml::value::Table; use serde::Serialize; @@ -756,6 +757,36 @@ impl<'a> Searcher<'a> { results } + pub fn tag_search(&self, root: &Page, tag: &str) -> Vec { + let mut results: Vec = vec![]; + for child in &root.children { + if let Some(child_page) = self.historian.resolve_to_page(&child.full_name) { + for result in self.tag_search(&child_page, tag) { + results.push(result); + } + + let mut content = String::new(); + if let Ok(mut file) = fs::File::open(&child_page.path) { + file.read_to_string(&mut content).unwrap(); + } + + let mut metadata = Table::new(); + parse_markdown(&content, &mut metadata); + + if metadata.contains_key("tags") { + let tags = metadata.get("tags").unwrap(); + if tags.is_array() && tags.as_array().contains(toml::Value::String(tag.to_owned())) { + results.push(SearchResult { + page: child_page, + matches: vec![] + }); + } + } + } + } + results + } + fn do_search(&self, root: &Page, results: &mut Vec, searcher: &mut grep::searcher::Searcher, matcher: &grep::regex::RegexMatcher) { for child in &root.children { if let Some(child_page) = self.historian.resolve_to_page(&child.full_name) { diff --git a/src/main.rs b/src/main.rs index 0b528e8..b9f1b57 100644 --- a/src/main.rs +++ b/src/main.rs @@ -82,6 +82,17 @@ async fn page<'r>( }) .render())) } + + if key == "tag" { + return PageResponder::Page(RawHtml(renderer.template("search.html") + .with_historian(&historian) + .with_page(&page) + .insert("results", &Searcher::new(&historian).tag_search(&page, value)) + .insert("options", &toml! { + dynamic = true + }) + .render())) + } } } @@ -208,6 +219,10 @@ struct Args { #[arg(long)] search: Option, + /// Search the wiki by tag + #[arg(long)] + tag: Option, + /// Search root #[arg(long)] search_root: Option @@ -276,6 +291,16 @@ async fn main() { return; } + if let Some(tag) = args.tag { + let searcher = Searcher::new(&historian); + let search_root = args.search_root.as_deref().unwrap_or(""); + let page = historian.resolve_to_page(&search_root).expect("failed to find page"); + for result in searcher.tag_search(&page, &tag) { + print_result(&result); + } + return; + } + rocket::build() .manage(historian) .manage(renderer)