├── LICENSE ├── README.md └── adaptive_image.rb /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Aaron Gustafson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Jekyll Adaptive Images 2 | 3 | An implementation of Adaptive Images with `srcset` and `sizes` using [Google’s open image resizing service](https://carlo.zottmann.org/2013/04/14/google-image-resizer/). 4 | 5 | The tag is simple: 6 | 7 | {% adaptive_image /path/to/image.jpg [attr="value"] %} 8 | 9 | You can add as many attributes as you want. 10 | 11 | ## Global Configuration 12 | 13 | To keep things simple and consistant, you can set up the standard sizes of your adaptive images in variables in `_config.yml`: 14 | 15 | adaptive_image: 16 | cache: 2592000 17 | srcset: 18 | - 1920 19 | - 600 20 | - 320 21 | sizes: 22 | - "(min-width:60em) 42.5em" 23 | - 100vw 24 | 25 | * `cache` is for the length of time you want to cache it (in seconds) 26 | * `srcset` is a list of sizes (in unitless pixel widths) you want to offer 27 | * `sizes` is the size configurations for layout purposes -------------------------------------------------------------------------------- /adaptive_image.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Author: Aaron Gustafson 3 | # Adaptive Images with the Google Image Resizer 4 | # For more, see https://carlo.zottmann.org/2013/04/14/google-image-resizer/ 5 | # 6 | # An implementation of Adaptive Images with `srcset` and `sizes` using [Google’s open image resizing service](https://carlo.zottmann.org/2013/04/14/google-image-resizer/). 7 | # 8 | # The tag is simple: 9 | # 10 | # {% adaptive_image /path/to/image.jpg [attr="value"] %} 11 | # 12 | # You can add as many attributes as you want. 13 | # 14 | # ## Global Configuration 15 | # 16 | # To keep things simple and consistant, you can set up the standard sizes of your adaptive images in variables in `_config.yml`: 17 | # 18 | # adaptive_image: 19 | # cache: 2592000 20 | # srcset: 21 | # - 1920 22 | # - 600 23 | # - 320 24 | # sizes: 25 | # - "(min-width:60em) 42.5em" 26 | # - 100vw 27 | # 28 | # * `cache` is for the length of time you want to cache it (in seconds) 29 | # * `srcset` is a list of sizes (in unitless pixel widths) you want to offer 30 | # * `sizes` is the size configurations for layout purposes 31 | # 32 | 33 | module Jekyll 34 | 35 | class AdaptiveImageTag < Liquid::Tag 36 | 37 | @url = nil 38 | 39 | def initialize(tag_name, tag_text, tokens) 40 | @url = 'https://images1-focus-opensocial.googleusercontent.com/gadgets/proxy?url=%{url}&resize_w=%{width}&container=focus&refresh=%{cache}' 41 | @tag_text = tag_text 42 | super 43 | end 44 | 45 | def render(context) 46 | render_markup = Liquid::Template.parse(@tag_text).render(context).gsub(/\\\{\\\{|\\\{\\%/, '\{\{' => '{{', '\{\%' => '{%') 47 | 48 | # Gather settings 49 | site = context.registers[:site] 50 | settings = site.config['adaptive_image'] 51 | 52 | markup = /^(?[^\s]+\.[a-zA-Z0-9]{3,4})\s*(?[\s\S]+)$/.match(render_markup) 53 | 54 | if markup 55 | 56 | # Assign defaults 57 | settings['cache'] ||= 2592000 58 | settings['srcset'] ||= [1920, 600, 320] 59 | sizes = settings['sizes'].join(',') || '100vw' 60 | smallest_src = nil 61 | src = nil 62 | 63 | # Process html attributes 64 | html_attr = if markup[:html_attr] 65 | Hash[ *markup[:html_attr].scan(/(?[^\s="]+)(?:="(?[^"]+)")?\s?/).flatten ] 66 | else 67 | {} 68 | end 69 | html_attr_string = html_attr.inject('') { |string, attrs| 70 | if attrs[1] 71 | string << "#{attrs[0]}=\"#{attrs[1]}\" " 72 | else 73 | string << "#{attrs[0]} " 74 | end 75 | } 76 | 77 | # set up the url 78 | original_source = markup[:image_src] 79 | if original_source[0] == '/' and original_source[1] != '/' 80 | original_source = "#{site.config['url']}#{original_source}" 81 | end 82 | 83 | # Add the src & srcset 84 | srcset = [] 85 | settings['srcset'].each do |size| 86 | the_src = @url % {url: original_source, width: size, cache: settings['cache']} 87 | the_src << " #{size}w" 88 | srcset << the_src 89 | if ! smallest_src or smalles_src > size 90 | smalles_src = size 91 | src = the_src 92 | end 93 | end 94 | srcset = srcset.join(',') 95 | html_attr_string << " src=\"#{src}\" srcset=\"#{srcset}\"" 96 | 97 | # Add sizes if it doesn’t exist 98 | if ! html_attr_string.include? 'sizes=' 99 | html_attr_string << " sizes=\"#{sizes}\"" 100 | end 101 | 102 | # Add alt if it doesn’t exist 103 | if ! html_attr_string.include? 'alt=' 104 | html_attr_string << ' alt=""' 105 | end 106 | 107 | "" 108 | end 109 | 110 | end 111 | end 112 | end 113 | 114 | Liquid::Template.register_tag('adaptive_image', Jekyll::AdaptiveImageTag) --------------------------------------------------------------------------------