use crate::directive::{DirectiveError, DirectiveImplementation, Processed}; use crate::page::PageMeta; use crate::site::Site; use crate::wikitext::ParsedDirective; use html_escape::encode_double_quoted_attribute; use log::trace; use std::path::Path; #[derive(Debug, Eq, PartialEq)] pub struct Img { src: String, link: bool, align: Option, alt: Option, class: Option, hspace: Option, height: Option, id: Option, title: Option, vspace: Option, width: Option, } impl DirectiveImplementation for Img { const REQUIRED: &'static [&'static str] = &[]; const ALLOWED: &'static [&'static str] = &[ "align", "alt", "class", "hspace", "id", "link", "size", "title", "vspace", ]; const ALLOW_ANY_UNNAMED: bool = true; fn from_parsed(p: &ParsedDirective) -> Self { let unnamed = p.unnamed_args().pop().unwrap(); let mut img = Img::new(unnamed.into()); let args = p.args(); if let Some(link) = args.get("link") { if *link == "no" { img.link(false); } } if let Some(size) = args.get("size") { if let Some((w, h)) = size.split_once('x') { if let Ok(w) = w.parse() { img.width(w); } if let Ok(h) = h.parse() { img.height(h); } } } if let Some(align) = args.get("align") { img.align(align.to_string()); } if let Some(alt) = args.get("alt") { img.alt(alt.to_string()); } if let Some(class) = args.get("class") { img.class(class.to_string()); } if let Some(hspace) = args.get("hspace") { img.hspace(hspace.to_string()); } if let Some(id) = args.get("id") { img.id(id.to_string()); } if let Some(title) = args.get("title") { img.title(title.to_string()); } if let Some(vspace) = args.get("vspace") { img.vspace(vspace.to_string()); } img } fn process(&self, site: &Site, meta: &mut PageMeta) -> Result { trace!( "verify image exists: {} on {}", self.src, meta.path().display() ); let src = site .resolve(meta.path(), Path::new(&self.src)) .map_err(|e| DirectiveError::Site(Box::new(e)))?; trace!("img src={:?}", src.display()); let mut img = String::new(); let src = Some(self.src.clone()); if self.link { img.push_str("'); } img.push_str("'); if self.link { img.push_str(""); } Ok(Processed::Markdown(img)) } } impl Img { fn new(src: String) -> Self { Self { src, link: true, align: None, alt: None, class: None, height: None, hspace: None, id: None, title: None, vspace: None, width: None, } } fn link(&mut self, link: bool) { self.link = link; } fn align(&mut self, align: String) { self.align = Some(align); } fn alt(&mut self, alt: String) { self.alt = Some(alt); } fn class(&mut self, class: String) { self.class = Some(class); } fn height(&mut self, h: usize) { self.height = Some(h); } fn hspace(&mut self, hspace: String) { self.hspace = Some(hspace); } fn id(&mut self, id: String) { self.id = Some(id); } fn title(&mut self, title: String) { self.title = Some(title); } fn vspace(&mut self, vspace: String) { self.vspace = Some(vspace); } fn width(&mut self, w: usize) { self.width = Some(w); } } fn push_attr(s: &mut String, name: &str, value: &Option) { if let Some(v) = value { s.push_str(&format!( " {}=\"{}\"", name, encode_double_quoted_attribute(v) )); } }