summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2022-09-08 16:01:47 +0000
committerLars Wirzenius <liw@liw.fi>2022-09-08 16:01:47 +0000
commitc6cb630275ef9edd8a9818a4883f2a2b59b4aa46 (patch)
treec3ccf40bdcba236758f7e1496475c9eef002869e
parent17bf42ac8c8cb1aeb145e6f8deeae62e5436e56f (diff)
parent57ecbab94bcc884c1e3264f3e117898f03074dc5 (diff)
downloadriki-c6cb630275ef9edd8a9818a4883f2a2b59b4aa46.tar.gz
Merge branch 'img' into 'main'
img directive Closes #12 See merge request larswirzenius/riki!51
-rw-r--r--riki.md67
-rw-r--r--src/directive/img.rs134
2 files changed, 196 insertions, 5 deletions
diff --git a/riki.md b/riki.md
index 9ec7d8e..988777b 100644
--- a/riki.md
+++ b/riki.md
@@ -428,6 +428,13 @@ 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
HTML page._
@@ -447,6 +454,66 @@ 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._
+
+The [ikiwiki img
+directive](http://ikiwiki.info/ikiwiki/directive/img/) allows
+arguments:
+
+> `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-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""
+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`
_Requirement: the `meta title` directive sets page title._
diff --git a/src/directive/img.rs b/src/directive/img.rs
index be165f8..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", "height", "link", "width", "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
}
}