jekyll-responsive_image 0.9.1 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|