Implement responsive_image_block tag
This commit is contained in:
parent
c8d48350b1
commit
6f9f13e62f
19
README.md
19
README.md
|
@ -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..." %}
|
{% 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
|
### 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.
|
You will need to create a template in order to use the `responsive_image` tag. Below are some sample templates to get you started.
|
||||||
|
|
|
@ -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"
|
|
@ -1,4 +1,4 @@
|
||||||
Feature: Jekyll responsive-image tag
|
Feature: Jekyll responsive_image tag
|
||||||
As a Jekyll template developer
|
As a Jekyll template developer
|
||||||
I want to include responsive images in my page
|
I want to include responsive images in my page
|
||||||
In order to best cater for devices of all sizes
|
In order to best cater for devices of all sizes
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
require 'fileutils'
|
require 'fileutils'
|
||||||
|
require 'yaml'
|
||||||
|
|
||||||
require 'jekyll'
|
require 'jekyll'
|
||||||
require 'rmagick'
|
require 'rmagick'
|
||||||
|
@ -6,6 +7,9 @@ require 'rmagick'
|
||||||
require 'jekyll/responsive_image/version'
|
require 'jekyll/responsive_image/version'
|
||||||
require 'jekyll/responsive_image/defaults'
|
require 'jekyll/responsive_image/defaults'
|
||||||
require 'jekyll/responsive_image/utils'
|
require 'jekyll/responsive_image/utils'
|
||||||
|
require 'jekyll/responsive_image/resize_handler'
|
||||||
require 'jekyll/responsive_image/tag'
|
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', Jekyll::ResponsiveImage::Tag)
|
||||||
|
Liquid::Template.register_tag('responsive_image_block', Jekyll::ResponsiveImage::Block)
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -12,72 +12,14 @@ module Jekyll
|
||||||
end
|
end
|
||||||
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)
|
def render(context)
|
||||||
config = ResponsiveImage.defaults.dup
|
config = ResponsiveImage.defaults.dup
|
||||||
config.merge!(context.registers[:site].config['responsive_image'])
|
config.merge!(context.registers[:site].config['responsive_image'])
|
||||||
|
|
||||||
|
resize_handler = ResizeHandler.new
|
||||||
img = Magick::Image::read(@attributes['path']).first
|
img = Magick::Image::read(@attributes['path']).first
|
||||||
@attributes['original'] = image_hash(@attributes['path'], img.columns, img.rows)
|
@attributes['original'] = Utils.image_hash(@attributes['path'], img.columns, img.rows)
|
||||||
@attributes['resized'] = resize_image(img, config)
|
@attributes['resized'] = resize_handler.resize_image(img, config)
|
||||||
|
|
||||||
image_template = @attributes['template'] || config['template']
|
image_template = @attributes['template'] || config['template']
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,18 @@ module Jekyll
|
||||||
end
|
end
|
||||||
result
|
result
|
||||||
end
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue