From 584ec41c7a997a4d7c60a1a9304da1291a25c2ea Mon Sep 17 00:00:00 2001 From: Nick Pegg Date: Wed, 7 May 2025 14:27:11 -0700 Subject: [PATCH] Some fixes - Render markdown descriptions - Don't include the cover in the album's images, but make sure we generate a thumbnail for it - Make extra sure we don't include slides dirs --- Cargo.lock | 41 +++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/generate.rs | 11 ++++++++++- src/generate/album_dir.rs | 25 ++++++++++++++++++------ src/main.rs | 1 + 5 files changed, 72 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f51acf4..ae9e3fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -431,6 +431,15 @@ dependencies = [ "version_check", ] +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width", +] + [[package]] name = "getrandom" version = "0.2.16" @@ -881,6 +890,7 @@ dependencies = [ "image", "log", "mktemp", + "pulldown-cmark", "rayon", "serde", "serde_yml", @@ -959,6 +969,25 @@ dependencies = [ "syn", ] +[[package]] +name = "pulldown-cmark" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e8bbe1a966bd2f362681a44f6edce3c2310ac21e4d5067a6e7ec396297a6ea0" +dependencies = [ + "bitflags 2.9.0", + "getopts", + "memchr", + "pulldown-cmark-escape", + "unicase", +] + +[[package]] +name = "pulldown-cmark-escape" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae" + [[package]] name = "qoi" version = "0.4.1" @@ -1438,12 +1467,24 @@ dependencies = [ "unic-common", ] +[[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + [[package]] name = "unicode-ident" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + [[package]] name = "utf8parse" version = "0.2.2" diff --git a/Cargo.toml b/Cargo.toml index dcce813..9415881 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ env_logger = "^0.11.8" fs_extra = "^1.3.0" image = "^0.25.6" log = "^0.4.27" +pulldown-cmark = "^0.13.0" rayon = "^1.10.0" serde = { version = "^1.0", features = ["derive"] } serde_yml = "^0.0.12" diff --git a/src/generate.rs b/src/generate.rs index b2d000d..2ff13c7 100644 --- a/src/generate.rs +++ b/src/generate.rs @@ -79,6 +79,7 @@ impl TryFrom<&AlbumDir> for AlbumContext { }; // Pick a cover image thumbnail and build a path to it + // TODO: If album has no images, pick the cover from one of the albums let cover_thumbnail_path = match &album.cover { Some(i) => Path::new("slides").join(&i.thumb_filename), None => PathBuf::from(""), @@ -147,12 +148,20 @@ fn copy_static(config: &Config) -> anyhow::Result<()> { fn generate_images(config: &Config, album: &AlbumDir) -> anyhow::Result<()> { let output_path = album.path.join(&config.output_dir); // TODO: progress bar ? - let all_images: Vec<&Image> = album.iter_all_images().collect(); + let mut all_images: Vec<&Image> = album.iter_all_images().collect(); + + // also resize cover image + if let Some(cover) = &album.cover { + all_images.push(cover); + } + all_images.par_iter().try_for_each(|img| { let orig_image = image::open(&img.path)?; // TODO: If orig_path is the same as the original image, and quick mode is on, skip to next // image + // + // TODO: Hard-link if it's supported, to save on hard drive space let orig_path = output_path.join(&img.path); log::info!( "Copying original {} -> {}", diff --git a/src/generate/album_dir.rs b/src/generate/album_dir.rs index 3c47888..5340c86 100644 --- a/src/generate/album_dir.rs +++ b/src/generate/album_dir.rs @@ -40,15 +40,19 @@ impl AlbumDir { if filename == "description.txt" { description = fs::read_to_string(entry_path)?; } else if filename == "description.md" { - let _conents = fs::read_to_string(entry_path)?; - // TODO: render markdown - todo!(); + log::debug!("Loading Markdown from {}", entry_path.display()); + let mut description = String::new(); + let contents = fs::read_to_string(&entry_path)?; + let parser = pulldown_cmark::Parser::new(&contents); + pulldown_cmark::html::push_html(&mut description, parser); } else { if filename.to_string_lossy().starts_with("cover") { cover = Some(Image::new( entry_path.strip_prefix(root)?.to_path_buf(), String::new(), )?); + // Don't include the cover in the set of images + continue; } let reader = ImageReader::open(&entry_path)?.with_guessed_format()?; @@ -60,9 +64,15 @@ impl AlbumDir { if entry_path.with_extension("txt").exists() { description = fs::read_to_string(entry_path.with_extension("txt"))?; } else if entry_path.with_extension("md").exists() { - let _contents = fs::read(entry_path.with_extension("md"))?; - // TODO: render markdown - todo!(); + log::debug!( + "Loading Markdown from {}", + entry_path.with_extension("md").display() + ); + let mut description = String::new(); + let contents = + fs::read_to_string(&entry_path.with_extension("md"))?; + let parser = pulldown_cmark::Parser::new(&contents); + pulldown_cmark::html::push_html(&mut description, parser); } images.push(Image::new( @@ -80,6 +90,8 @@ impl AlbumDir { } else if dirname == "site" { // Is a generated site dir, don't descend into it continue; + } else if dirname == "slides" { + continue; } children.push(AlbumDir::from_path(&entry_path, root)?); @@ -90,6 +102,7 @@ impl AlbumDir { if cover.is_none() && !images.is_empty() { cover = Some(images[0].clone()); } + // TODO: sort children and albums alphabetically Ok(AlbumDir { path: p.strip_prefix(root)?.to_path_buf(), diff --git a/src/main.rs b/src/main.rs index 2ca6d06..e662672 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,7 @@ use std::path::Path; fn main() -> anyhow::Result<()> { env_logger::init(); let cli = Cli::parse(); + // TODO: canonicalize path? To allow ~/foo/bar let album_path = Path::new(&cli.album_path); match cli.subcommand {