Implement responsive_image_block tag

This commit is contained in:
Joseph Wynn 2014-12-07 13:06:28 +00:00
parent c8d48350b1
commit 6f9f13e62f
8 changed files with 160 additions and 62 deletions

View File

@ -78,6 +78,25 @@ Any extra attributes will be passed straight to the template as variables.
{% responsive_image path: assets/image.jpg alt: "Lorem ipsum..." title: "Lorem ipsum..." %}
```
### Liquid variables as attributes
You can use Liquid variables as attributes with the `responsive_image_block` tag. This tag works in exactly the same way as the `responsive_image` tag, but is implemented as a block tag to allow for more complex logic.
> **Important!** The attributes in the `responsive_image_block` tag are parsed as YAML, so whitespace and indentation are important!
```
{% assign path = 'assets/test.png' %}
{% assign alt = 'Lorem ipsum...' %}
{% responsive_image_block %}
path: {{ path }}
alt: {{ alt }}
{% if title %}
title: {{ title }}
{% endif %}
{% endresponsive_image_block %}
```
### Template
You will need to create a template in order to use the `responsive_image` tag. Below are some sample templates to get you started.

View File

@ -0,0 +1,46 @@
Feature: Jekyll responsive_image_block tag
As a Jekyll template developer
I want to include Liquid variables when rendering my responsive images
In order to dynamically generate my responsive images
Scenario: Simple image tag
Given I have a responsive_image configuration with:
"""
template: _includes/responsive-image.html
"""
And I have a file "index.html" with:
"""
{% assign path = 'assets/test.png' %}
{% assign alt = 'Lorem ipsum' %}
{% responsive_image_block %}
path: {{ path }}
title: Magic rainbow adventure!
alt: {{ alt }}
{% endresponsive_image_block %}
"""
When I run Jekyll
Then I should see "<img alt=\"Lorem ipsum\" src=\"/assets/test.png\" title=\"Magic rainbow adventure!\"" in "_site/index.html"
Scenario: More complex logic in the block tag
Given I have a responsive_image configuration with:
"""
template: _includes/responsive-image.html
"""
And I have a file "index.html" with:
"""
{% assign path = 'assets/test.png' %}
{% assign alt = 'Lorem ipsum' %}
{% responsive_image_block %}
path: {{ path }}
{% if another_alt %}
alt: {{ another_alt }}
{% else %}
alt: {{ alt }}
{% endif %}
{% endresponsive_image_block %}
"""
When I run Jekyll
Then I should see "<img alt=\"Lorem ipsum\" src=\"/assets/test.png\"" in "_site/index.html"

View File

@ -1,4 +1,4 @@
Feature: Jekyll responsive-image tag
Feature: Jekyll responsive_image tag
As a Jekyll template developer
I want to include responsive images in my page
In order to best cater for devices of all sizes

View File

@ -1,4 +1,5 @@
require 'fileutils'
require 'yaml'
require 'jekyll'
require 'rmagick'
@ -6,6 +7,9 @@ require 'rmagick'
require 'jekyll/responsive_image/version'
require 'jekyll/responsive_image/defaults'
require 'jekyll/responsive_image/utils'
require 'jekyll/responsive_image/resize_handler'
require 'jekyll/responsive_image/tag'
require 'jekyll/responsive_image/block'
Liquid::Template.register_tag('responsive_image', Jekyll::ResponsiveImage::Tag)
Liquid::Template.register_tag('responsive_image_block', Jekyll::ResponsiveImage::Block)

View File

@ -0,0 +1,23 @@
module Jekyll
class ResponsiveImage
class Block < Liquid::Block
def render(context)
config = ResponsiveImage.defaults.dup
config.merge!(context.registers[:site].config['responsive_image'])
attributes = YAML.load(super)
image_template = attributes['template'] || config['template']
resize_handler = ResizeHandler.new
img = Magick::Image::read(attributes['path']).first
attributes['original'] = Utils.image_hash(attributes['path'], img.columns, img.rows)
attributes['resized'] = resize_handler.resize_image(img, config)
partial = File.read(image_template)
template = Liquid::Template.parse(partial)
template.render!(attributes)
end
end
end
end

View File

@ -0,0 +1,52 @@
module Jekyll
class ResponsiveImage
class ResizeHandler
def resize_image(img, config)
resized = []
config['sizes'].each do |size|
width = size['width']
ratio = width.to_f / img.columns.to_f
height = (img.rows.to_f * ratio).round
next unless needs_resizing?(img, width)
filepath = format_output_path(config['output_path_format'], img.filename, width, height)
resized.push(Utils.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)
i.write(filepath) do |f|
f.quality = size['quality'] || config['default_quality']
end
i.destroy!
end
resized
end
def format_output_path(format, path, width, height)
params = Utils.symbolize_keys(Utils.image_hash(path, width, height))
format % params
end
def needs_resizing?(img, width)
img.columns > width
end
def ensure_output_dir_exists!(dir)
unless Dir.exists?(dir)
Jekyll.logger.info "Creating output directory #{dir}"
FileUtils.mkdir_p(dir)
end
end
end
end
end

View File

@ -12,72 +12,14 @@ module Jekyll
end
end
def resize_image(img, config)
resized = []
config['sizes'].each do |size|
width = size['width']
ratio = width.to_f / img.columns.to_f
height = (img.rows.to_f * ratio).round
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)
i.write(filepath) do |f|
f.quality = size['quality'] || config['default_quality']
end
i.destroy!
end
resized
end
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)
img.columns > width
end
def ensure_output_dir_exists!(dir)
unless Dir.exists?(dir)
Jekyll.logger.info "Creating output directory #{dir}"
FileUtils.mkdir_p(dir)
end
end
# Build a hash containing image information
def image_hash(path, width, height)
{
'path' => path,
'basename' => File.basename(path),
'filename' => File.basename(path, '.*'),
'extension' => File.extname(path).delete('.'),
'width' => width,
'height' => height,
}
end
def render(context)
config = ResponsiveImage.defaults.dup
config.merge!(context.registers[:site].config['responsive_image'])
resize_handler = ResizeHandler.new
img = Magick::Image::read(@attributes['path']).first
@attributes['original'] = image_hash(@attributes['path'], img.columns, img.rows)
@attributes['resized'] = resize_image(img, config)
@attributes['original'] = Utils.image_hash(@attributes['path'], img.columns, img.rows)
@attributes['resized'] = resize_handler.resize_image(img, config)
image_template = @attributes['template'] || config['template']

View File

@ -8,6 +8,18 @@ module Jekyll
end
result
end
# Build a hash containing image information
def self.image_hash(path, width, height)
{
'path' => path,
'basename' => File.basename(path),
'filename' => File.basename(path, '.*'),
'extension' => File.extname(path).delete('.'),
'width' => width,
'height' => height,
}
end
end
end
end