lumeland / lume

🔥 Static site generator for Deno 🦕
https://lume.land
MIT License
1.9k stars 89 forks source link

Picture plugin #384

Closed oscarotero closed 1 year ago

oscarotero commented 1 year ago

Enter your suggestions in details:

It would work combined with the Imagick plugin, to generate different versions of the same image by scanning the HTML and searching for <picture> elements with the formats and/or sizes attribute. For example:

<picture formats="avif,jpg" sizes="1x,300w,2x">
    <img src="/my-image.jpg">
</picture>

This would generate the following code:

<picture>
    <source srcset="/my-image-1x.avif, /my-image-300w.avif 300w, /my-image-2x.avif 2x" />
    <source srcset="/my-image-1x.jpg, /my-image-300w.jpg 300w, /my-image-2x.jpg 2x" />
    <img src="/my-image.jpg">
</picture>

And all versions of /my-image.jpg.

Related issue: #356

cgwrench commented 1 year ago

I'd love to see a picture plugin.

In terms of how I would like to see this work, rather than having to wrap every image in a site with a picture tag, I'd like to have a central place where the configuration of what formats and sizes I want (like already exists with the Imagick plugin). The plugin would then wrap any img element (that is not already wrapped in a picture element?) with a picture element and include the other formats. If that's too greedy, then having an attribute on an img tag to signal that it should be processed by the picture plugin (like the inline plugin) would be great too. Your suggestion of having the plugin search for picture elements and formats/sizes attributes could be a great way to override the central configuration of the plugin.

My motivation for suggesting this is that I often author pages in Markdown, and I'd like to not have to change how I'm including images. I'd like the standard way of including images to just work with this new plugin.

~It would also be nice to (perhaps as an option) include a hash of the generated images in the file name, to support long-term caching of these resources. Could that be supported here (or is that already handled by another plugin)?~ I've just seen that this is covered by https://github.com/lumeland/lume/issues/352.

oscarotero commented 1 year ago

Okay, it makes sense. Maybe it could work in this way:

<div img-formats="avif,jpg" img-sizes="1x,300w,2x">
   <!-- All images here will be affected -->
</div>
<picture img-formats="avif,jpg" img-sizes="1x,300w,2x">
   <!-- Only this picture will be affected -->
</picture>
<!-- This image will be converted to a picture -->
<img src="" img-formats="avif,jpg" img-sizes="1x,300w,2x">

I not sure about the name of the attributes. And I'd like to have only one attribute instead of two. Maybe something like img="avif,jpg | 1x,300w,2x".

cgwrench commented 1 year ago

Hi @oscarotero. That looks good, but I don't think I was clear with my suggestion. Sorry about that, let me try again.

When I suggested a default configuration, I was imaging something set when registering the plugin, something like:

site.use(picture({
  widths: [300, 600],
  formats: ["webp", "jpg"]
}));

I've lifted these option names from Eleventy's image plugin, feel free to pick different options.

Alternatively, the imagick plugin uses shared data. Is there a way we could do the same for a picture plugin, so there is consistency between the two plugins?

With this configuration in place, I'd imagine all images will be affected. Perhaps then your suggestion of img-formats/img-sizes or img attributes would then allow users to override the default configuration for a given image.

I hope this makes sense, do let me know if I've not been clear about anything. And, of course, feel free to ignore all of this if you choose!

oscarotero commented 1 year ago

@cgwrench Yes, I got your suggestion, but don't think it's a good idea to specify this globally in the _config file. A website can have different sections, with different configurations for pictures (It can have a blog, a photo gallery, a landing page, etc). So I think this feature should be defined in the templates, in order to have different configurations per page (or even per section in the same page).

If you want to define this behavior for the entire site, you can add the attribute in a layout shared to all pages. For example:

<!doctype html>
<html>
<head>
...
</head>

<body img="avif,jpg | 1x,300w,2x">
    {{ content | safe }}
</body>
</html>

To define this value using shared data, you can create a variable in a _data file and use it in the templates. For example:

# _data.yml

picture_config: "avif,jpg | 1x,300w,2x"
<!doctype html>
<html>
<head>
...
</head>

<body img="{{ picture_config }}">
    {{ content | safe }}
</body>
</html>

Does it works for you?

cgwrench commented 1 year ago

That does work for me, thanks!

oscarotero commented 1 year ago

Work in progress here: https://github.com/lumeland/experimental-plugins/tree/main/picture

You can see an example here: https://github.com/lumeland/experimental-plugins/blob/main/picture/demo/index.njk

The current syntax is:

oscarotero commented 1 year ago

It will be available in the coming v1.18.0. I'm closing this