jekyll-responsive_image 0.9.1 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +73 -28
- data/features/fixtures/_includes/custom-template.html +1 -1
- data/features/fixtures/_includes/responsive-image.html +4 -5
- data/features/responsive-image.feature +19 -1
- data/lib/jekyll/responsive_image/defaults.rb +13 -0
- data/lib/jekyll/responsive_image/tag.rb +91 -0
- data/lib/jekyll/responsive_image/utils.rb +13 -0
- data/lib/jekyll/responsive_image/version.rb +1 -1
- data/lib/jekyll/responsive_image.rb +6 -96
- metadata +4 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ed00bfad560bc67b74bd57aeae4cf8245a3584ec
|
4
|
+
data.tar.gz: 4f9315a2ac66b01e024b1c650783e864ff712b65
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1951e99caf0c73b6716810dfa26043085f9b3aa522f3a393c5963ab85cd613bb5657ebb23c3af0a056a951200536e6af4a5c0b9c3a561d83f26d27a488da663f
|
7
|
+
data.tar.gz: 39505e832aad11402d47a1f4d617a6dca827e19104652a359f846f838b55f2c1b0891776ac663054e449383ddaa7977f966e5ddfd89f5824c178a3354ce98185
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -27,15 +27,35 @@ An example configuration is below.
|
|
27
27
|
|
28
28
|
```yaml
|
29
29
|
responsive_image:
|
30
|
-
|
30
|
+
# [Required]
|
31
|
+
# Path to the image template.
|
32
|
+
template: _includes/responsive-image.html
|
31
33
|
|
32
|
-
#
|
33
|
-
#
|
34
|
+
# [Optional, Default: 85]
|
35
|
+
# Quality to use when resizing images.
|
36
|
+
default_quality: 90
|
37
|
+
|
38
|
+
# [Optional, Default: []]
|
39
|
+
# An array of resize configuration objects. Each object must contain at least
|
40
|
+
# a `width` value.
|
34
41
|
sizes:
|
35
|
-
- width: 480
|
42
|
+
- width: 480 # [Required] How wide the resized image will be.
|
43
|
+
quality: 80 # [Optional] Overrides default_quality for this size.
|
36
44
|
- width: 800
|
37
|
-
quality: 90 # Override JPEG quality (default is 85). Optional.
|
38
45
|
- width: 1400
|
46
|
+
quality: 90
|
47
|
+
|
48
|
+
# [Optional, Default: assets/resized/%{filename}-%{width}x%{height}.%{extension}]
|
49
|
+
# The template used when generating filenames for resized images.
|
50
|
+
#
|
51
|
+
# Parameters available are:
|
52
|
+
# %{basename} Basename of the file (assets/some-file.jpg => some-file.jpg)
|
53
|
+
# %{filename} Basename without the extension (assets/some-file.jpg => some-file)
|
54
|
+
# %{extension} Extension of the file (assets/some-file.jpg => jpg)
|
55
|
+
# %{width} Width of the resized image
|
56
|
+
# %{height} Height of the resized image
|
57
|
+
#
|
58
|
+
output_path_format: assets/resized/%{width}/%{basename}
|
39
59
|
```
|
40
60
|
|
41
61
|
## Usage
|
@@ -60,35 +80,60 @@ Any extra attributes will be passed straight to the template as variables.
|
|
60
80
|
|
61
81
|
### Template
|
62
82
|
|
63
|
-
You will need to create a template in order to use the `responsive_image` tag.
|
83
|
+
You will need to create a template in order to use the `responsive_image` tag. Below are some sample templates to get you started.
|
84
|
+
|
85
|
+
#### Basic image tag with `srcset`
|
64
86
|
|
65
87
|
```html
|
66
88
|
<img src="/{{ path }}"
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
srcset="{% for i in resized %}
|
72
|
-
/{{ i.path }} {{ i.width }}w{% if forloop.last == false %},{% endif %}
|
73
|
-
{% endfor %}"
|
74
|
-
{% endif %}
|
75
|
-
>
|
89
|
+
srcset="
|
90
|
+
{% for i in resized %}/{{ i.path }} {{ i.width }}w,{% endfor %}
|
91
|
+
/{{ original.path }} {{ original.width }}w
|
92
|
+
">
|
76
93
|
```
|
77
94
|
|
78
|
-
####
|
95
|
+
#### Responsive images using [Imager.js](https://github.com/BBC-News/Imager.js/)
|
79
96
|
|
80
|
-
|
97
|
+
> This template assumes an `output_path_format` of `assets/resized/%{width}/%{basename}`
|
81
98
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
99
|
+
```html
|
100
|
+
{% assign smallest = resized | sort: 'width' | first %}
|
101
|
+
|
102
|
+
<div class="responsive-image">
|
103
|
+
<img class="responsive-image__placeholder" src="/{{ smallest.path }}">
|
104
|
+
<div class="responsive-image__delayed" data-src="/assets/resized/{width}/{{ original.basename }}"></div>
|
105
|
+
</div>
|
106
|
+
|
107
|
+
<script>
|
108
|
+
new Imager('.responsive-image__delayed', {
|
109
|
+
availableWidths: [{{ resized | map: 'width' | join: ', ' }}]
|
110
|
+
onImagesReplaced: function() {
|
111
|
+
$('.responsive-image__placeholder').hide();
|
112
|
+
}
|
113
|
+
});
|
114
|
+
</script>
|
115
|
+
```
|
116
|
+
|
117
|
+
### Template Variables
|
87
118
|
|
88
|
-
|
119
|
+
The following variables are available in the template:
|
89
120
|
|
90
|
-
| Variable
|
91
|
-
|
92
|
-
| `path`
|
93
|
-
| `
|
94
|
-
| `
|
121
|
+
| Variable | Type | Description |
|
122
|
+
|----------- |--------|------------------------------------------------------------------------------------------------------|
|
123
|
+
| `path` | String | The path of the unmodified image. This is always the same as the `path` attribute passed to the tag. |
|
124
|
+
| `resized` | Array | An array of all the resized images. Each image is an **Image Object**. |
|
125
|
+
| `original` | Object | An **Image Object** containing information about the original image. |
|
126
|
+
| `*` | String | Any other attributes will be passed to the template verbatim as strings. |
|
127
|
+
|
128
|
+
#### Image Objects
|
129
|
+
|
130
|
+
Image objects (like `original` and each object in `resized`) contain the following properties:
|
131
|
+
|
132
|
+
| Variable | Type | Description |
|
133
|
+
|-------------|---------|-------------------------------------------------------------------------|
|
134
|
+
| `path` | String | The path to the image. |
|
135
|
+
| `width` | Integer | The width of the image. |
|
136
|
+
| `height` | Integer | The height of the image. |
|
137
|
+
| `basename` | String | Basename of the file (`assets/some-file.jpg` => `some-file.jpg`). |
|
138
|
+
| `filename` | String | Basename without the extension (`assets/some-file.jpg` => `some-file`). |
|
139
|
+
| `extension` | String | Extension of the file (`assets/some-file.jpg` => `jpg`). |
|
@@ -1 +1 @@
|
|
1
|
-
{{ resized | map: 'width' }}
|
1
|
+
[{{ resized | map: 'width' | join: ', ' }}]
|
@@ -1,5 +1,4 @@
|
|
1
|
-
<img alt="{{ alt }}" src="/{{ path }}" title="{{ title }}"
|
2
|
-
{% for i in resized %}
|
3
|
-
|
4
|
-
|
5
|
-
"{% endif %}>
|
1
|
+
<img alt="{{ alt }}" src="/{{ path }}" title="{{ title }}" srcset="
|
2
|
+
{% for i in resized %}/{{ i.path }} {{ i.width }}w,{% endfor %}
|
3
|
+
/{{ original.path }} {{ original.width }}w
|
4
|
+
">
|
@@ -55,6 +55,7 @@ Feature: Jekyll responsive-image tag
|
|
55
55
|
Then I should see "<img alt=\"\" src=\"/assets/test.png\"" in "_site/index.html"
|
56
56
|
And I should see "/assets/resized/test-100x50.png 100w" in "_site/index.html"
|
57
57
|
And I should see "/assets/resized/test-200x100.png 200w" in "_site/index.html"
|
58
|
+
And I should see "/assets/test.png 300w" in "_site/index.html"
|
58
59
|
And the file "assets/resized/test-100x50.png" should exist
|
59
60
|
And the file "assets/resized/test-200x100.png" should exist
|
60
61
|
|
@@ -65,10 +66,27 @@ Feature: Jekyll responsive-image tag
|
|
65
66
|
sizes:
|
66
67
|
- width: 100
|
67
68
|
- width: 200
|
69
|
+
- width: 300
|
68
70
|
"""
|
69
71
|
And I have a file "index.html" with:
|
70
72
|
"""
|
71
73
|
{% responsive_image path: assets/test.png template: _includes/custom-template.html %}
|
72
74
|
"""
|
73
75
|
When I run Jekyll
|
74
|
-
Then I should see "
|
76
|
+
Then I should see "[100, 200, 300]" in "_site/index.html"
|
77
|
+
|
78
|
+
Scenario: Overriding the generated filenames
|
79
|
+
Given I have a responsive_image configuration with:
|
80
|
+
"""
|
81
|
+
template: _includes/responsive-image.html
|
82
|
+
output_path_format: assets/%{basename}-resized/%{width}/%{filename}-%{height}.%{extension}
|
83
|
+
sizes:
|
84
|
+
- width: 100
|
85
|
+
"""
|
86
|
+
And I have a file "index.html" with:
|
87
|
+
"""
|
88
|
+
{% responsive_image path: assets/test.png %}
|
89
|
+
"""
|
90
|
+
When I run Jekyll
|
91
|
+
Then I should see "/assets/test.png-resized/100/test-50.png 100w" in "_site/index.html"
|
92
|
+
And the file "assets/test.png-resized/100/test-50.png" should exist
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Jekyll
|
2
|
+
class ResponsiveImage
|
3
|
+
@defaults = {
|
4
|
+
'default_quality' => 85,
|
5
|
+
'output_path_format' => 'assets/resized/%{filename}-%{width}x%{height}.%{extension}',
|
6
|
+
'sizes' => [],
|
7
|
+
}.freeze
|
8
|
+
|
9
|
+
class << self
|
10
|
+
attr_reader :defaults
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Jekyll
|
2
|
+
class ResponsiveImage
|
3
|
+
class Tag < Liquid::Tag
|
4
|
+
def initialize(tag_name, markup, tokens)
|
5
|
+
super
|
6
|
+
|
7
|
+
@attributes = {}
|
8
|
+
|
9
|
+
markup.scan(::Liquid::TagAttributes) do |key, value|
|
10
|
+
# Strip quotes from around attribute values
|
11
|
+
@attributes[key] = value.gsub(/^['"]|['"]$/, '')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def resize_image(img, config)
|
16
|
+
resized = []
|
17
|
+
|
18
|
+
config['sizes'].each do |size|
|
19
|
+
width = size['width']
|
20
|
+
ratio = width.to_f / img.columns.to_f
|
21
|
+
height = (img.rows.to_f * ratio).round
|
22
|
+
|
23
|
+
next unless needs_resizing?(img, width)
|
24
|
+
|
25
|
+
filepath = format_output_path(config['output_path_format'], img.filename, width, height)
|
26
|
+
resized.push(image_hash(filepath, width, height))
|
27
|
+
|
28
|
+
# Don't resize images more than once
|
29
|
+
next if File.exists?(filepath)
|
30
|
+
|
31
|
+
ensure_output_dir_exists!(File.dirname(filepath))
|
32
|
+
|
33
|
+
Jekyll.logger.info "Generating #{filepath}"
|
34
|
+
|
35
|
+
i = img.scale(ratio)
|
36
|
+
i.write(filepath) do |f|
|
37
|
+
f.quality = size['quality'] || config['default_quality']
|
38
|
+
end
|
39
|
+
|
40
|
+
i.destroy!
|
41
|
+
end
|
42
|
+
|
43
|
+
resized
|
44
|
+
end
|
45
|
+
|
46
|
+
def format_output_path(format, path, width, height)
|
47
|
+
params = Utils.symbolize_keys(image_hash(path, width, height))
|
48
|
+
format % params
|
49
|
+
end
|
50
|
+
|
51
|
+
def needs_resizing?(img, width)
|
52
|
+
img.columns > width
|
53
|
+
end
|
54
|
+
|
55
|
+
def ensure_output_dir_exists!(dir)
|
56
|
+
unless Dir.exists?(dir)
|
57
|
+
Jekyll.logger.info "Creating output directory #{dir}"
|
58
|
+
FileUtils.mkdir_p(dir)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Build a hash containing image information
|
63
|
+
def image_hash(path, width, height)
|
64
|
+
{
|
65
|
+
'path' => path,
|
66
|
+
'basename' => File.basename(path),
|
67
|
+
'filename' => File.basename(path, '.*'),
|
68
|
+
'extension' => File.extname(path).delete('.'),
|
69
|
+
'width' => width,
|
70
|
+
'height' => height,
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
def render(context)
|
75
|
+
config = ResponsiveImage.defaults.dup
|
76
|
+
config.merge!(context.registers[:site].config['responsive_image'])
|
77
|
+
|
78
|
+
img = Magick::Image::read(@attributes['path']).first
|
79
|
+
@attributes['original'] = image_hash(@attributes['path'], img.columns, img.rows)
|
80
|
+
@attributes['resized'] = resize_image(img, config)
|
81
|
+
|
82
|
+
image_template = @attributes['template'] || config['template']
|
83
|
+
|
84
|
+
partial = File.read(image_template)
|
85
|
+
template = Liquid::Template.parse(partial)
|
86
|
+
|
87
|
+
template.render!(@attributes)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -1,101 +1,11 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
1
3
|
require 'jekyll'
|
2
4
|
require 'rmagick'
|
3
5
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
def initialize(tag_name, markup, tokens)
|
10
|
-
super
|
11
|
-
|
12
|
-
@attributes = {}
|
13
|
-
@markup = markup
|
14
|
-
|
15
|
-
@markup.scan(::Liquid::TagAttributes) do |key, value|
|
16
|
-
# Strip quotes from around attribute values
|
17
|
-
@attributes[key] = value.gsub(/^['"]|['"]$/, '')
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def resize_image(path, config)
|
22
|
-
sizes = config['sizes']
|
23
|
-
|
24
|
-
return if sizes.empty?
|
25
|
-
|
26
|
-
output_dir = config['output_dir']
|
27
|
-
ensure_output_dir_exists!(output_dir)
|
28
|
-
|
29
|
-
resized = []
|
30
|
-
img = Magick::Image::read(path).first
|
31
|
-
|
32
|
-
sizes.each do |size|
|
33
|
-
width = size['width']
|
34
|
-
ratio = width.to_f / img.columns.to_f
|
35
|
-
height = (img.rows.to_f * ratio).round
|
36
|
-
|
37
|
-
filename = resized_filename(path, width, height)
|
38
|
-
newpath = "#{output_dir}/#{filename}"
|
39
|
-
|
40
|
-
next unless needs_resizing?(img, width)
|
41
|
-
|
42
|
-
resized.push({
|
43
|
-
'width' => width,
|
44
|
-
'height' => height,
|
45
|
-
'path' => newpath,
|
46
|
-
})
|
47
|
-
|
48
|
-
# Don't resize images more than once
|
49
|
-
next if File.exists?(newpath)
|
50
|
-
|
51
|
-
Jekyll.logger.info "Generating #{newpath}"
|
52
|
-
|
53
|
-
i = img.scale(ratio)
|
54
|
-
i.write(newpath) do |f|
|
55
|
-
f.quality = size['quality'] || DEFAULT_QUALITY
|
56
|
-
end
|
57
|
-
|
58
|
-
i.destroy!
|
59
|
-
end
|
60
|
-
|
61
|
-
resized
|
62
|
-
end
|
63
|
-
|
64
|
-
# Insert resize information into a file path
|
65
|
-
#
|
66
|
-
# resized_filename(/foo/bar/file.name.jpg, 500, 300)
|
67
|
-
# => /foo/bar/file.name-500x300.jpg
|
68
|
-
#
|
69
|
-
def resized_filename(path, width, height)
|
70
|
-
File.basename(path).sub(/\.([^.]+)$/, "-#{width}x#{height}.\\1")
|
71
|
-
end
|
72
|
-
|
73
|
-
def needs_resizing?(img, width)
|
74
|
-
img.columns > width
|
75
|
-
end
|
76
|
-
|
77
|
-
def ensure_output_dir_exists!(dir)
|
78
|
-
unless Dir.exists?(dir)
|
79
|
-
Jekyll.logger.info "Creating output directory #{dir}"
|
80
|
-
Dir.mkdir(dir)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def render(context)
|
85
|
-
config = context.registers[:site].config['responsive_image']
|
86
|
-
config['output_dir'] ||= 'assets/resized'
|
87
|
-
config['sizes'] ||= []
|
88
|
-
|
89
|
-
@attributes['template'] ||= config['template']
|
90
|
-
@attributes['resized'] = resize_image(@attributes['path'], config)
|
91
|
-
|
92
|
-
partial = File.read(@attributes['template'])
|
93
|
-
template = Liquid::Template.parse(partial)
|
94
|
-
|
95
|
-
template.render!(@attributes)
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
6
|
+
require 'jekyll/responsive_image/version'
|
7
|
+
require 'jekyll/responsive_image/defaults'
|
8
|
+
require 'jekyll/responsive_image/utils'
|
9
|
+
require 'jekyll/responsive_image/tag'
|
100
10
|
|
101
11
|
Liquid::Template.register_tag('responsive_image', Jekyll::ResponsiveImage::Tag)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jekyll-responsive_image
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joseph Wynn
|
@@ -64,6 +64,9 @@ files:
|
|
64
64
|
- index.html
|
65
65
|
- jekyll-responsive_image.gemspec
|
66
66
|
- lib/jekyll/responsive_image.rb
|
67
|
+
- lib/jekyll/responsive_image/defaults.rb
|
68
|
+
- lib/jekyll/responsive_image/tag.rb
|
69
|
+
- lib/jekyll/responsive_image/utils.rb
|
67
70
|
- lib/jekyll/responsive_image/version.rb
|
68
71
|
- test-index.html
|
69
72
|
homepage: https://github.com/wildlyinaccurate/jekyll-responsive-image
|