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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dc0a20c9cc1f1bfd10aef481ca55672377b9379f
4
- data.tar.gz: 60044f0efde1042917c727817d597e11e38ca40a
3
+ metadata.gz: ed00bfad560bc67b74bd57aeae4cf8245a3584ec
4
+ data.tar.gz: 4f9315a2ac66b01e024b1c650783e864ff712b65
5
5
  SHA512:
6
- metadata.gz: 2c21adf98bc2bd32e379bb7721f7ff2ce9149f2a351dd00f99ead6f52b935ae82a30ce1d62fb76abbef567c5d0ad701e36ffc31617bef6b609ce316ae6c23d1d
7
- data.tar.gz: fb4cd91b2570b517e2e05662e1117adce75616b973a48faf6147e3f4ecc802be260e81e7e74a49b4be166025160c826cf3a4a6f7d1ea3dbe29519dd4419a5bc4
6
+ metadata.gz: 1951e99caf0c73b6716810dfa26043085f9b3aa522f3a393c5963ab85cd613bb5657ebb23c3af0a056a951200536e6af4a5c0b9c3a561d83f26d27a488da663f
7
+ data.tar.gz: 39505e832aad11402d47a1f4d617a6dca827e19104652a359f846f838b55f2c1b0891776ac663054e449383ddaa7977f966e5ddfd89f5824c178a3354ce98185
data/.gitignore CHANGED
@@ -1,2 +1,3 @@
1
1
  coverage
2
2
  Gemfile.lock
3
+ jekyll-responsive_image-*.gem
data/README.md CHANGED
@@ -27,15 +27,35 @@ An example configuration is below.
27
27
 
28
28
  ```yaml
29
29
  responsive_image:
30
- template: '_includes/responsive-image.html' # Path to the template to render. Required.
30
+ # [Required]
31
+ # Path to the image template.
32
+ template: _includes/responsive-image.html
31
33
 
32
- # An array of resize configurations. When this array is empty (or not specified),
33
- # no resizing will take place.
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 # How wide the resized image will be. Required
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. A sample template is below.
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
- alt="{{ alt }}"
68
- title="{{ title }}"
69
-
70
- {% if resized %}
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
- #### Template Variables
95
+ #### Responsive images using [Imager.js](https://github.com/BBC-News/Imager.js/)
79
96
 
80
- The following variables are available in the template:
97
+ > This template assumes an `output_path_format` of `assets/resized/%{width}/%{basename}`
81
98
 
82
- | Variable | Type | Description |
83
- |-----------|--------|------------------------------------------------------------------------------------------------------|
84
- | `path` | String | The path of the unmodified image. This is always the same as the `path` attribute passed to the tag. |
85
- | `resized` | Array | An array of all the resized images. Each image contains the properties listed below. |
86
- | `*` | String | Any other attributes will be passed to the template verbatim as strings. |
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
- Each element in the `resized` array contains the following properties:
119
+ The following variables are available in the template:
89
120
 
90
- | Variable | Type | Description |
91
- |----------|----------|----------------------------------|
92
- | `path` | String | The path of the resized image. |
93
- | `width` | Integer | The width of the resized image. |
94
- | `height` | Integer | The height of the resized image. |
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 }}"{% if resized %} srcset="
2
- {% for i in resized %}
3
- /{{ i.path }} {{ i.width }}w{% if forloop.last == false %},{% endif %}
4
- {% endfor %}
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 "100200" in "_site/index.html"
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
@@ -0,0 +1,13 @@
1
+ module Jekyll
2
+ class ResponsiveImage
3
+ class Utils
4
+ def self.symbolize_keys(hash)
5
+ result = {}
6
+ hash.each_key do |key|
7
+ result[key.to_sym] = hash[key]
8
+ end
9
+ result
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,5 +1,5 @@
1
1
  module Jekyll
2
2
  class ResponsiveImage
3
- VERSION = '0.9.1'.freeze
3
+ VERSION = '0.10.0'.freeze
4
4
  end
5
5
  end
@@ -1,101 +1,11 @@
1
+ require 'fileutils'
2
+
1
3
  require 'jekyll'
2
4
  require 'rmagick'
3
5
 
4
- module Jekyll
5
- class ResponsiveImage
6
- class Tag < Liquid::Tag
7
- DEFAULT_QUALITY = 85
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.9.1
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