···11+---
22+maudit: patch
33+---
44+55+Return a newtype around a String when using `Image.render()` so that images can be used directly in supported templating languages
+1-1
crates/maudit/src/assets.rs
···1010mod script;
1111mod style;
1212mod tailwind;
1313-pub use image::{Image, ImageFormat, ImageOptions, ImagePlaceholder, RenderWithAlt};
1313+pub use image::{Image, ImageFormat, ImageOptions, ImagePlaceholder, RenderWithAlt, RenderedImage};
1414pub use script::Script;
1515pub use style::{Style, StyleOptions};
1616pub use tailwind::TailwindPlugin;
+41-5
crates/maudit/src/assets/image.rs
···11+use std::fmt::Display;
12use std::hash::Hash;
23use std::{path::PathBuf, sync::OnceLock, time::Instant};
34···128129 get_placeholder(&self.path)
129130 }
130131132132+ // Get the dimensions of an image. Note that at this time, unsupported file formats such as SVGs will return (0, 0).
131133 pub fn dimensions(&self) -> (u32, u32) {
132134 image_dimensions(&self.path).unwrap_or((0, 0))
133135 }
···435437436438/// Trait to render an image with an alt text.
437439pub trait RenderWithAlt {
438438- fn render(&self, alt: &str) -> String;
440440+ /// Render the image as an HTML `<img>` tag with the given alt text.
441441+ fn render(&self, alt: &str) -> RenderedImage;
442442+}
443443+444444+/// Newtype around a String representing a rendered image HTML tag.
445445+#[derive(Clone, Debug, PartialEq, Eq)]
446446+pub struct RenderedImage(String);
447447+448448+impl From<String> for RenderedImage {
449449+ fn from(value: String) -> Self {
450450+ RenderedImage(value)
451451+ }
452452+}
453453+454454+impl Display for RenderedImage {
455455+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
456456+ write!(f, "{}", self.0)
457457+ }
439458}
440459441460impl RenderWithAlt for Image {
442442- fn render(&self, alt: &str) -> String {
461461+ fn render(&self, alt: &str) -> RenderedImage {
443462 let (width, height) = self.dimensions();
444463464464+ // HACK: Only include width and height attributes if they are greater than 0
465465+ // This is to workaround the fact that some unsupported image formats by `image` will return (0, 0)
466466+ let width_attr = if width > 0 {
467467+ format!(r#" width="{width}""#)
468468+ } else {
469469+ String::new()
470470+ };
471471+472472+ let height_attr = if height > 0 {
473473+ format!(r#" height="{height}""#)
474474+ } else {
475475+ String::new()
476476+ };
477477+445478 format!(
446446- r#"<img src="{}" width="{}" height="{}" loading="lazy" decoding="async" alt="{}"/>"#,
447447- self.url, width, height, alt
448448- )
479479+ r#"<img src="{src}"{width_attr}{height_attr} loading="lazy" decoding="async" alt="{alt}"/>"#,
480480+ src = self.url,
481481+ width_attr = width_attr,
482482+ height_attr = height_attr,
483483+ alt = alt
484484+ ).into()
449485 }
450486}
···2828}
2929```
30303131-Maudit implements the `Render` trait for scripts and styles, allowing one to use them directly in Maud templates.
3131+Maudit implements the `Render` trait for images, scripts and styles, allowing one to use them directly in Maud templates.
32323333```rs
3434use maud::{html, Markup};
···4040impl Route for Index {
4141 fn render(&self, ctx: &mut PageContext) -> impl Into<RenderResult> {
4242 let style = ctx.add_style("style.css");
4343+ let image = ctx.add_image("logo.png");
43444445 html! {
4546 (style) // Will render to a <link> tag for the CSS file
4747+ (image.render("The logo of my product")) // Will render to an <img> tag for the image
4648 }
4749 }
4850}
···5557maud = "0.27"
5658```
57595858-The `maud` feature is enabled by default. If you have disabled default features, you can enable it manually:
6060+The `maud` feature is enabled by default. If you have disabled default features, you can enable it manually by editing your `Cargo.toml`:
59616062```toml
6161-maudit = { version = "0.6", features = ["maud"] }
6363+maudit = { version = "...", features = ["maud"] }
6264```