From 2715d55520771e7e7138940d226ff61e960833be Mon Sep 17 00:00:00 2001 From: Joseph Wynn Date: Sat, 6 Dec 2014 22:28:21 +0000 Subject: [PATCH] Swap output_dir for more powerful output_path_format --- README.md | 51 ++++++++++++++++--- .../fixtures/_includes/custom-template.html | 2 +- features/responsive-image.feature | 19 ++++++- lib/jekyll/responsive_image.rb | 3 ++ lib/jekyll/responsive_image/defaults.rb | 6 +-- lib/jekyll/responsive_image/tag.rb | 30 +++++------ lib/jekyll/responsive_image/utils.rb | 13 +++++ 7 files changed, 96 insertions(+), 28 deletions(-) create mode 100644 lib/jekyll/responsive_image/utils.rb diff --git a/README.md b/README.md index 886ff78..29ec71c 100644 --- a/README.md +++ b/README.md @@ -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 ``` +#### 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 %} + +
+ +
+
+ + +``` + ### 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`). | diff --git a/features/fixtures/_includes/custom-template.html b/features/fixtures/_includes/custom-template.html index 668d293..a27f53a 100644 --- a/features/fixtures/_includes/custom-template.html +++ b/features/fixtures/_includes/custom-template.html @@ -1 +1 @@ -{{ resized | map: 'width' }} +[{{ resized | map: 'width' | join: ', ' }}] diff --git a/features/responsive-image.feature b/features/responsive-image.feature index e509860..646bad0 100644 --- a/features/responsive-image.feature +++ b/features/responsive-image.feature @@ -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 diff --git a/lib/jekyll/responsive_image.rb b/lib/jekyll/responsive_image.rb index d5bb0eb..0feb605 100644 --- a/lib/jekyll/responsive_image.rb +++ b/lib/jekyll/responsive_image.rb @@ -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) diff --git a/lib/jekyll/responsive_image/defaults.rb b/lib/jekyll/responsive_image/defaults.rb index 94464f7..f47d4a9 100644 --- a/lib/jekyll/responsive_image/defaults.rb +++ b/lib/jekyll/responsive_image/defaults.rb @@ -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 diff --git a/lib/jekyll/responsive_image/tag.rb b/lib/jekyll/responsive_image/tag.rb index 7c49fc4..70432e6 100644 --- a/lib/jekyll/responsive_image/tag.rb +++ b/lib/jekyll/responsive_image/tag.rb @@ -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 diff --git a/lib/jekyll/responsive_image/utils.rb b/lib/jekyll/responsive_image/utils.rb new file mode 100644 index 0000000..f13d7e7 --- /dev/null +++ b/lib/jekyll/responsive_image/utils.rb @@ -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