Swap output_dir for more powerful output_path_format

This commit is contained in:
Joseph Wynn 2014-12-06 22:28:21 +00:00
parent b9407d113b
commit 2715d55520
7 changed files with 96 additions and 28 deletions

View File

@ -30,6 +30,18 @@ responsive_image:
template: '_includes/responsive-image.html' # Path to the template to render. Required.
default_quality: 90 # Quality to use when resizing images. Default value is 85. Optional.
# The template used when generating filenames for resized images.
# Default value is 'assets/resized/%{filename}-%{width}x%{height}.%{extension}'
#
# Parameters available are:
# %{basename} Basename of the file (assets/some-file.jpg => some-file.jpg)
# %{filename} Basename without the extension (assets/some-file.jpg => some-file)
# %{extension} Extension of the file (assets/some-file.jpg => jpg)
# %{width} Width of the resized image
# %{height} Height of the resized image
#
output_path_format: assets/resized/%{width}/%{basename}
# An array of resize configurations. When this array is empty (or not specified),
# no resizing will take place.
sizes:
@ -62,7 +74,9 @@ Any extra attributes will be passed straight to the template as variables.
### Template
You will need to create a template in order to use the `responsive_image` tag. A sample template is below.
You will need to create a template in order to use the `responsive_image` tag. Below are some sample templates to get you started.
#### Basic image tag with `srcset`
```html
<img src="/{{ path }}"
@ -72,6 +86,28 @@ You will need to create a template in order to use the `responsive_image` tag. A
">
```
#### Responsive images using [Imager.js](https://github.com/BBC-News/Imager.js/)
> This template assumes an `output_path_format` of `assets/resized/%{width}/%{basename}`
```html
{% assign smallest = resized | sort: 'width' | first %}
<div class="responsive-image">
<img class="responsive-image__placeholder" src="/{{ smallest.path }}">
<div class="responsive-image__delayed" data-src="/assets/resized/{width}/{{ original.basename }}"></div>
</div>
<script>
new Imager('.responsive-image__delayed', {
availableWidths: [{{ resized | map: 'width' | join: ', ' }}]
onImagesReplaced: function() {
$('.responsive-image__placeholder').hide();
}
});
</script>
```
### Template Variables
The following variables are available in the template:
@ -87,8 +123,11 @@ The following variables are available in the template:
Image objects (like `original` and each object in `resized`) contain the following properties:
| Variable | Type | Description |
|----------|----------|--------------------------|
| `path` | String | The path to the image. |
| `width` | Integer | The width of the image. |
| `height` | Integer | The height of the image. |
| Variable | Type | Description |
|-------------|---------|-------------------------------------------------------------------------|
| `path` | String | The path to the image. |
| `width` | Integer | The width of the image. |
| `height` | Integer | The height of the image. |
| `basename` | String | Basename of the file (`assets/some-file.jpg` => `some-file.jpg`). |
| `filename` | String | Basename without the extension (`assets/some-file.jpg` => `some-file`). |
| `extension` | String | Extension of the file (`assets/some-file.jpg` => `jpg`). |

View File

@ -1 +1 @@
{{ resized | map: 'width' }}
[{{ resized | map: 'width' | join: ', ' }}]

View File

@ -66,10 +66,27 @@ Feature: Jekyll responsive-image tag
sizes:
- width: 100
- width: 200
- width: 300
"""
And I have a file "index.html" with:
"""
{% responsive_image path: assets/test.png template: _includes/custom-template.html %}
"""
When I run Jekyll
Then I should see "100200" in "_site/index.html"
Then I should see "[100, 200, 300]" in "_site/index.html"
Scenario: Overriding the generated filenames
Given I have a responsive_image configuration with:
"""
template: _includes/responsive-image.html
output_path_format: assets/%{basename}-resized/%{width}/%{filename}-%{height}.%{extension}
sizes:
- width: 100
"""
And I have a file "index.html" with:
"""
{% responsive_image path: assets/test.png %}
"""
When I run Jekyll
Then I should see "/assets/test.png-resized/100/test-50.png 100w" in "_site/index.html"
And the file "assets/test.png-resized/100/test-50.png" should exist

View File

@ -1,8 +1,11 @@
require 'fileutils'
require 'jekyll'
require 'rmagick'
require 'jekyll/responsive_image/version'
require 'jekyll/responsive_image/defaults'
require 'jekyll/responsive_image/utils'
require 'jekyll/responsive_image/tag'
Liquid::Template.register_tag('responsive_image', Jekyll::ResponsiveImage::Tag)

View File

@ -1,9 +1,9 @@
module Jekyll
class ResponsiveImage
@defaults = {
'default_quality' => 85,
'output_dir' => 'assets/resized',
'sizes' => [],
'default_quality' => 85,
'output_path_format' => 'assets/resized/%{filename}-%{width}x%{height}.%{extension}',
'sizes' => [],
}.freeze
class << self

View File

@ -13,9 +13,6 @@ module Jekyll
end
def resize_image(img, config)
output_dir = config['output_dir']
ensure_output_dir_exists!(output_dir)
resized = []
config['sizes'].each do |size|
@ -23,16 +20,16 @@ module Jekyll
ratio = width.to_f / img.columns.to_f
height = (img.rows.to_f * ratio).round
filename = resized_filename(img.filename, width, height)
filepath = "#{output_dir}/#{filename}"
next unless needs_resizing?(img, width)
filepath = format_output_path(config['output_path_format'], img.filename, width, height)
resized.push(image_hash(filepath, width, height))
# Don't resize images more than once
next if File.exists?(filepath)
ensure_output_dir_exists!(File.dirname(filepath))
Jekyll.logger.info "Generating #{filepath}"
i = img.scale(ratio)
@ -46,13 +43,9 @@ module Jekyll
resized
end
# Insert resize information into a file path
#
# resized_filename(/foo/bar/file.name.jpg, 500, 300)
# => /foo/bar/file.name-500x300.jpg
#
def resized_filename(path, width, height)
File.basename(path).sub(/\.([^.]+)$/, "-#{width}x#{height}.\\1")
def format_output_path(format, path, width, height)
params = Utils.symbolize_keys(image_hash(path, width, height))
format % params
end
def needs_resizing?(img, width)
@ -62,16 +55,19 @@ module Jekyll
def ensure_output_dir_exists!(dir)
unless Dir.exists?(dir)
Jekyll.logger.info "Creating output directory #{dir}"
Dir.mkdir(dir)
FileUtils.mkdir_p(dir)
end
end
# Build a hash containing image information
def image_hash(path, width, height)
{
'path' => path,
'width' => width,
'height' => height,
'path' => path,
'basename' => File.basename(path),
'filename' => File.basename(path, '.*'),
'extension' => File.extname(path).delete('.'),
'width' => width,
'height' => height,
}
end

View File

@ -0,0 +1,13 @@
module Jekyll
class ResponsiveImage
class Utils
def self.symbolize_keys(hash)
result = {}
hash.each_key do |key|
result[key.to_sym] = hash[key]
end
result
end
end
end
end