summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian T <julian@jtle.dk>2021-07-26 12:33:35 +0200
committerJulian T <julian@jtle.dk>2021-07-26 12:33:35 +0200
commit0ddf24fa0be620fc10cc07247b2c738b32943042 (patch)
tree7bf46891e4da4a9aa1b46417c33072fb9a0e6e57
parentc3c69b160f4c5fd851fd1a49c01f633a56351f5d (diff)
Added rendering of simple template
-rw-r--r--Cargo.toml2
-rw-r--r--src/context.rs59
-rw-r--r--src/main.rs12
-rw-r--r--src/picture.rs15
-rw-r--r--src/piece.rs25
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::<Result<(), ConfigError>>()?;
+
+ 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<String, tera::Value>) -> tera::Result<Value> {
+ 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<Config, ConfigError> {
let content = fs::read_to_string(path)?;
@@ -122,3 +169,9 @@ impl From<glob::PatternError> for ConfigError {
ConfigError::CompilePattern(error)
}
}
+
+impl From<tera::Error> 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::<Vec<Piece>>();
- 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<String>,
- hash: md5::Digest,
- path: PathBuf,
+ pub taken: Option<String>,
+ hash: String,
+ pub path: PathBuf,
}
pub struct Converter<'a> {
@@ -32,7 +33,7 @@ pub struct Converter<'a> {
pic: &'a Picture,
}
-fn hash_reader<R: Read>(reader: &mut R) -> Result<md5::Digest, io::Error> {
+fn hash_reader<R: Read>(reader: &mut R) -> Result<String, io::Error> {
let mut hash = md5::Context::new();
let mut buff = [0; 1024];
@@ -46,7 +47,7 @@ fn hash_reader<R: Read>(reader: &mut R) -> Result<md5::Digest, io::Error> {
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<PathBuf, ImageError> {
- 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<String>,
+}
+
+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<Self, ConversionError> {
+ 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<String> = 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,
})
}
}