From 9e44884dded63e8f838b1d80fd6e500834968ad1 Mon Sep 17 00:00:00 2001 From: Gregory Marco Date: Sun, 4 May 2025 00:30:43 -0500 Subject: [PATCH] Distinguish attachments, which are non-markdown files that should be served/copied directly, not processed into a template. --- make-dev-environment | 3 +- src/lib.rs | 66 +++++++++++++++++++++++++++++++++++--------- src/main.rs | 2 ++ 3 files changed, 57 insertions(+), 14 deletions(-) diff --git a/make-dev-environment b/make-dev-environment index a16136c..dda18a6 100755 --- a/make-dev-environment +++ b/make-dev-environment @@ -1,4 +1,5 @@ -#!/usr/bin/env -S guix shell -D -f guix.scm rust-analyzer -- sh +#!/usr/bin/env -S guix shell pkg-config rust-analyzer -- sh +##!/usr/bin/env -S guix shell -D -f guix.scm rust-analyzer -- sh ##!/usr/bin/env -S guix shell -D -f guix.scm -- sh #export LIBCLANG_PATH=$GUIX_ENVIRONMENT/lib/libclang.so export CC=gcc diff --git a/src/lib.rs b/src/lib.rs index e4aa1aa..426f42b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ static DEFAULT_INDEX_FILENAME: &'static str = "README.md"; static DEFAULT_TEMPLATES_PATH: &'static str = "templates"; static DEFAULT_TOML_FILENAME: &'static str = "Historian.toml"; +static MD_EXTENSION: &'static str = ".md"; extern crate pulldown_cmark; extern crate tera; @@ -63,10 +64,14 @@ impl Historian { Err(_) => None, Ok(metadata) => { let mut children = vec![]; + let mut attachments = vec![]; if metadata.is_dir() { for entry in fs::read_dir(&file_path).unwrap() { - let child = entry.unwrap().file_name().into_string().unwrap(); - if !(child.starts_with(".") || child == self.index_filename || child == DEFAULT_TOML_FILENAME) { + let entry_file = entry.unwrap(); + let child = entry_file.file_name().into_string().unwrap(); + if entry_file.metadata().unwrap().is_file() && !child.ends_with(MD_EXTENSION) { + attachments.push(child); + } else if !(child.starts_with(".") || child == self.index_filename || child == DEFAULT_TOML_FILENAME) { children.push(child); } } @@ -99,12 +104,31 @@ impl Historian { parent: parent_page, path: file_path, is_directory: metadata.is_dir(), - children + children, + attachments }) } } } + pub fn resolve_to_attachment(&self, name: &str) -> Option { + if name.ends_with(MD_EXTENSION) { + return None; + } + + let file_path = self.source_root.clone().join(Path::new(name)); + match fs::metadata(&file_path) { + Err(_) => None, + Ok(metadata) => { + if metadata.is_dir() { + None + } else { + Some(file_path) + } + } + } + } + // Creates a struct for a new page. // The page is not saved until an edit is submitted. pub fn start_page(&self, name: &str) -> Page { @@ -128,7 +152,8 @@ impl Historian { parent: None, path: file_path, is_directory, - children: vec![] + children: vec![], + attachments: vec![] } } @@ -264,7 +289,8 @@ pub struct Page { pub url: String, pub is_directory: bool, pub parent: Option>, - pub children: Vec + pub children: Vec, + pub attachments: Vec } #[derive(Serialize)] @@ -462,33 +488,47 @@ pub fn export_wiki(historian: &Historian, renderer: &PageRenderer, output_path: for resource_name in renderer.resource_names() { let mut resource_output_path: PathBuf = output_path.into(); resource_output_path.push(&resource_name); - println!("export resource {} to {:?}", resource_name, resource_output_path); - fs::copy(renderer.resolve_to_resource(&resource_name).unwrap(), resource_output_path).unwrap(); + export_resource(renderer.resolve_to_resource(&resource_name).unwrap(), output_path); } export_wiki_page(historian, renderer, "", output_path); } +fn export_resource(resource_path: PathBuf, output_path: &str) { + let mut resource_output_path: PathBuf = output_path.into(); + let resource_name = resource_path.file_name().unwrap().to_str().unwrap(); + resource_output_path.push(&resource_name); + println!("export resource {} to {:?}", resource_name, resource_output_path); + fs::copy(resource_path, resource_output_path).unwrap(); +} + fn export_wiki_page(historian: &Historian, renderer: &PageRenderer, name: &str, output_path: &str) { if let Some(page) = historian.resolve_to_page(name) { let page_path: PathBuf = page.full_name.to_owned().replace(".md", ".html").into(); let mut page_output_path: PathBuf = output_path.into(); page_output_path.push(&page_path); - if page.is_directory { + let page_html_output_path = if page.is_directory { println!("create directory {:?}", page_output_path); fs::create_dir_all(&page_output_path); - page_output_path.push("index.html"); - } + page_output_path.join("index.html") + } else { + page_output_path.clone() + }; - println!("export: {} to {:?}", page.full_name, page_output_path); + println!("export: {} to {:?}", page.full_name, page_html_output_path); let page_html = renderer.render_page_template("page.html", historian, &page, toml! { dynamic = false }.as_table().unwrap()).replace(".md", ".html"); - let mut page_html_file = fs::File::create(page_output_path).unwrap(); + let mut page_html_file = fs::File::create(page_html_output_path).unwrap(); page_html_file.write_all(page_html.as_bytes()); - + + for attachment in page.attachments { + let attachment_path = page_path.join(attachment); + export_resource(attachment_path, page_output_path.to_str().unwrap()); + } + for child in page.children { let child_path = page_path.join(child); export_wiki_page(historian, renderer, child_path.to_str().unwrap(), output_path); diff --git a/src/main.rs b/src/main.rs index 06d2932..5a9f524 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,6 +35,8 @@ async fn page<'r>( let path_str = path.to_str().unwrap(); if let Some(resource_path) = renderer.resolve_to_resource(path_str) { Some(PageResponder::File(NamedFile::open(resource_path).await.unwrap())) + } else if let Some(attachment_path) = historian.resolve_to_attachment(path_str) { + Some(PageResponder::File(NamedFile::open(attachment_path).await.unwrap())) } else { historian.resolve_to_page(path_str).map(|page| { if let Some(query) = origin.query() {