diff options
author | Lars Wirzenius <liw@liw.fi> | 2022-09-08 19:00:46 +0300 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2022-09-08 19:00:46 +0300 |
commit | 57ecbab94bcc884c1e3264f3e117898f03074dc5 (patch) | |
tree | c3ccf40bdcba236758f7e1496475c9eef002869e | |
parent | 2a52a50a70d49eac255c9e5c12f3036b3fc6bc2e (diff) | |
download | riki-57ecbab94bcc884c1e3264f3e117898f03074dc5.tar.gz |
feat: implement the img directive
Sponsored-by: author
-rw-r--r-- | riki.md | 63 | ||||
-rw-r--r-- | src/directive/img.rs | 134 |
2 files changed, 178 insertions, 19 deletions
@@ -428,6 +428,11 @@ then command fails ### `img` +The [ikiwiki img directive][] allow including images in the site +source tree. + +[ikiwiki img directive](http://ikiwiki.info/ikiwiki/directive/img/) + #### Simple image inclusion _Requirement: the `img` directive embeds an image in the generated @@ -449,6 +454,34 @@ then file output/index.html contains "<img src="img.jpg"" This is a dummy JPEG image. ~~~ +#### Image size + +_Requirement: the `img` directive can set size._ + +From the [ikiwiki img directive][] documentation: + +> `size`---The size parameter is optional, defaulting to full size. +> You can specify only the width or the height, and the other value +> will be calculated based on it: "200x", "x200". + +~~~scenario +given an installed riki +given file site/index.mdwn from img-size +given file site/a.jpg from jpeg +given file site/b.jpg from jpeg +given file site/c.jpg from jpeg +when I run riki build site output +then file output/index.html contains "<img src="a.jpg" width="100" height="200">" +then file output/index.html contains "<img src="b.jpg" width="100">" +then file output/index.html contains "<img src="c.jpg" height="200">" +~~~ + +~~~{#img-size .file .markdown} +[[!img a.jpg size="100x200"]]] +[[!img b.jpg size="100x"]]] +[[!img c.jpg size="x200"]]] +~~~ + #### Image attributes _Requirement: the `img` directive allows useful attributes to be set._ @@ -457,26 +490,28 @@ The [ikiwiki img directive](http://ikiwiki.info/ikiwiki/directive/img/) allows arguments: -* `size`---The size parameter is optional, defaulting to full size. - You can specify only the width or the height, and the other value - will be calculated based on it: "200x", "x200". -* `alt`, `title`, `class`, `align`, `id`, `hspace`, and - `vspace`---These are passed through unchanged to the html img tag. +> `alt`, `title`, `class`, `align`, `id`, `hspace`, and +> `vspace`---These are passed through unchanged to the html img tag. ~~~scenario given an installed riki -given file site/index.mdwn from img +given file site/index.mdwn from img-attr given file site/img.jpg from jpeg when I run riki build site output +when I run cat output/index.html then file output/index.html contains "<img src="img.jpg"" -~~~ - -~~~{#img .file .markdown} -[[!img img.jpg]]] -~~~ - -~~~{#jpeg .file} -This is a dummy JPEG image. +then file output/index.html contains "alt="halt malt"" +then file output/index.html contains "title="tightle"" +then file output/index.html contains "class="klass"" +then file output/index.html contains "align="malign"" +then file output/index.html contains "id="kid"" +then file output/index.html contains "hspace="hspc"" +then file output/index.html contains "vspace="vspc"" +~~~ + +~~~{#img-attr .file .markdown} +[[!img img.jpg alt="halt malt" title="tightle" class="klass" align="malign" + id="kid" hspace="hspc" vspace="vspc"]]] ~~~ ### `meta title` diff --git a/src/directive/img.rs b/src/directive/img.rs index 51b35f4..0e6cc79 100644 --- a/src/directive/img.rs +++ b/src/directive/img.rs @@ -2,23 +2,80 @@ use crate::error::SiteError; 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, + align: Option<String>, + alt: Option<String>, + class: Option<String>, + hspace: Option<String>, + height: Option<usize>, + id: Option<String>, + title: Option<String>, + vspace: Option<String>, + width: Option<usize>, } impl Img { pub const REQUIRED: &'static [&'static str] = &[]; pub const ALLOWED: &'static [&'static str] = &[ - "alt", "caption", "class", "link", "size", "align", + "align", "alt", "class", "hspace", "id", "size", "title", "vspace", ]; pub const ALLOW_ANY_UNNAMED: bool = true; - pub fn new(src: String) -> Self { - Self { src } + fn new(src: String) -> Self { + Self { + src, + align: None, + alt: None, + class: None, + height: None, + hspace: None, + id: None, + title: None, + vspace: None, + width: None, + } + } + + 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); } pub fn process(&self, site: &Site, meta: &mut PageMeta) -> Result<String, SiteError> { @@ -29,13 +86,80 @@ impl Img { ); let src = site.resolve(meta.path(), Path::new(&self.src))?; trace!("img src={:?}", src.display()); - Ok(format!("![]({})", self.src)) + let mut img = format!("<img src=\"{}\"", self.src); + if let Some(w) = self.width { + img.push_str(&format!(" width=\"{}\"", w)); + } + if let Some(h) = self.height { + img.push_str(&format!(" height=\"{}\"", h)); + } + push_attr(&mut img, "align", &self.align); + push_attr(&mut img, "alt", &self.alt); + push_attr(&mut img, "class", &self.class); + push_attr(&mut img, "hspace", &self.hspace); + push_attr(&mut img, "id", &self.id); + push_attr(&mut img, "title", &self.title); + push_attr(&mut img, "vspace", &self.vspace); + img.push('>'); + Ok(img) + } +} + +fn push_attr(s: &mut String, name: &str, value: &Option<String>) { + if let Some(v) = value { + s.push_str(&format!( + " {}=\"{}\"", + name, + encode_double_quoted_attribute(v) + )); } } impl From<&ParsedDirective> for Img { fn from(p: &ParsedDirective) -> Self { let unnamed = p.unnamed_args().pop().unwrap(); - Img::new(unnamed.into()) + let mut img = Img::new(unnamed.into()); + let args = p.args(); + + 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 } } |