From 0ddf24fa0be620fc10cc07247b2c738b32943042 Mon Sep 17 00:00:00 2001 From: Julian T Date: Mon, 26 Jul 2021 12:33:35 +0200 Subject: Added rendering of simple template --- Cargo.toml | 2 +- src/context.rs | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- src/main.rs | 12 +++++------- src/picture.rs | 15 ++++++++------- src/piece.rs | 25 +++++++++++++++++++++---- 5 files changed, 91 insertions(+), 22 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 385d8a6..7450ed5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -tera = "1.12" +tera = "1" image = "0.23" serde = { version = "1.0", features = ["derive"] } serde_yaml = "0.8" diff --git a/src/context.rs b/src/context.rs index 55f3f97..925db0b 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,9 +1,13 @@ -use structopt::StructOpt; -use serde::Deserialize; use std::collections::HashMap; use std::fs; use std::io; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; + +use structopt::StructOpt; +use serde::Deserialize; +use tera::{Tera, Filter, Value}; + +const TMPL_FILES: &'static [&'static str] = &["index.html"]; #[derive(Debug, StructOpt)] #[structopt(name = "gallery")] @@ -30,6 +34,7 @@ pub enum ConfigError { Reading(io::Error), Parsing(serde_yaml::Error), CompilePattern(glob::PatternError), + CompileTemplate(tera::Error), } #[derive(Deserialize, Debug)] @@ -41,11 +46,17 @@ pub struct Config { pub imageglob_compiled: glob::Pattern, } +struct ReltoFilter { + dir: PathBuf, +} + #[derive(Debug)] pub struct Context { pub options: Options, pub config: Config, pub imgdir: PathBuf, + + pub tmpl: Tera, } impl Context { @@ -61,10 +72,22 @@ impl Context { } } + // Compile templates + let mut tera = Tera::default(); + let tmpl_dir = opts.load.join("templates"); + TMPL_FILES.iter().map(|fname| -> Result<(), ConfigError> { + let path = tmpl_dir.join(fname); + tera.add_template_file(path, Some(fname))?; + Ok(()) + }).collect::>()?; + + tera.register_filter("relto_build", ReltoFilter::new(&opts.builddir)); + Ok(Context { options: opts, config: config, imgdir: imgdir, + tmpl: tera, }) } @@ -83,6 +106,30 @@ impl Context { } } +impl ReltoFilter { + pub fn new(dir: &Path) -> Self { + ReltoFilter { + dir: dir.to_path_buf(), + } + } +} + +impl Filter for ReltoFilter { + fn filter(&self, value: &Value, _: &HashMap) -> tera::Result { + if let Value::String(path) = value { + let path = PathBuf::from(path); + match path.strip_prefix(&self.dir) { + Ok(relto) => Ok(Value::String(relto.to_string_lossy().to_string())), + Err(err) => Err(tera::Error::call_filter("relto", err)), + } + } else { + Err(tera::Error::msg("Input to relto filter must be string")) + } + } + + fn is_safe(&self) -> bool { true } +} + impl Config { fn load_from_file(path: &PathBuf) -> Result { let content = fs::read_to_string(path)?; @@ -122,3 +169,9 @@ impl From for ConfigError { ConfigError::CompilePattern(error) } } + +impl From for ConfigError { + fn from(error: tera::Error) -> Self { + ConfigError::CompileTemplate(error) + } +} diff --git a/src/main.rs b/src/main.rs index 28fe0c9..b647cdc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,13 +11,11 @@ fn main() { let ctx = Context::new_with_args().unwrap(); - for file in ctx.get_image_files().unwrap() { - println!("{}", file.display()); + let pieces = ctx.get_image_files().unwrap().iter() + .map(|file| Picture::new_from_file(&file).unwrap()) + .map(|pic| Piece::new(&ctx, pic).unwrap()) + .collect::>(); - let pic = Picture::new_from_file(&file).unwrap(); - println!("{:?}", pic); + piece::create_index(&ctx, &pieces[..]).unwrap(); - let piece = Piece::new(&ctx, pic).unwrap(); - println!("{:?}", piece); - } } diff --git a/src/picture.rs b/src/picture.rs index f92876c..76a33df 100644 --- a/src/picture.rs +++ b/src/picture.rs @@ -5,6 +5,7 @@ use std::io::{Read, Seek}; use image::io::Reader as ImageReader; use image::error::ImageError; use image::imageops; +use serde::Serialize; use crate::context::Context; @@ -20,11 +21,11 @@ pub enum ConversionError { ImageError(ImageError), } -#[derive(Debug)] +#[derive(Debug, Serialize)] pub struct Picture { - taken: Option, - hash: md5::Digest, - path: PathBuf, + pub taken: Option, + hash: String, + pub path: PathBuf, } pub struct Converter<'a> { @@ -32,7 +33,7 @@ pub struct Converter<'a> { pic: &'a Picture, } -fn hash_reader(reader: &mut R) -> Result { +fn hash_reader(reader: &mut R) -> Result { let mut hash = md5::Context::new(); let mut buff = [0; 1024]; @@ -46,7 +47,7 @@ fn hash_reader(reader: &mut R) -> Result { hash.consume(&buff[..count]) } - Ok(hash.compute()) + Ok(format!("{:?}", hash.compute())) } impl Picture { @@ -106,7 +107,7 @@ impl Converter<'_> { } pub fn get_size(&mut self, ctx: &Context, size: u32) -> Result { - let hash = md5::compute(format!("{},{},{:?}", size, ctx.options.ext, self.pic.hash)); + let hash = md5::compute(format!("{},{},{}", size, ctx.options.ext, self.pic.hash)); let name = format!("{:?}.{}", hash, ctx.options.ext); let path = ctx.imgdir.join(name); diff --git a/src/piece.rs b/src/piece.rs index a0cc18e..2c0b545 100644 --- a/src/piece.rs +++ b/src/piece.rs @@ -1,22 +1,39 @@ use std::path::PathBuf; use crate::picture::{Picture, ConversionError}; use crate::context::Context; +use tera::Context as WebContext; +use serde::Serialize; -#[derive(Debug)] +#[derive(Debug, Serialize)] pub struct Piece { pic: Picture, + scaled_path: PathBuf, - thumb_path: PathBuf, + //thumb_path: PathBuf, + info: Option, +} + +pub fn create_index(ctx: &Context, pieces: &[Piece]) -> Result<(), tera::Error> { + let mut web_ctx = WebContext::new(); + web_ctx.insert("pieces", pieces); + + println!("render: {}", ctx.tmpl.render("index.html", &web_ctx)?); + Ok(()) } impl Piece { pub fn new(ctx: &Context, pic: Picture) -> Result { + println!("Creating piece from file {}", pic.path.display()); let mut conv = pic.convert()?; let scaled_path = conv.get_size(ctx, ctx.options.size_scaled)?; - let thumb_path = conv.get_size(ctx, ctx.options.size_thumb)?; + //let thumb_path = conv.get_size(ctx, ctx.options.size_thumb)?; + + let info: Option = pic.path.file_name() + .map(|name| name.to_str()).flatten() + .map(|name| ctx.config.info.get(name).map(|s| s.clone())).flatten(); Ok(Piece { - pic, scaled_path, thumb_path, + pic, scaled_path, info, }) } } -- cgit v1.2.3