Compare commits
84 Commits
big-ass-re
...
master
Author | SHA1 | Date |
---|---|---|
Joseph Wynn | dda6d748c8 | |
Joseph Wynn | a31c454ed1 | |
Joseph Wynn | f2be2c53be | |
Joseph Wynn | 6cc3a082a1 | |
Joseph Wynn | 2f7c0124eb | |
Márton Salomváry | 25c6695da4 | |
Joseph Wynn | 7679f4b8f5 | |
Daniel Pietzsch | 82e868966c | |
Daniel Pietzsch | fbc35b8ef9 | |
Daniel Pietzsch | 749e6cc068 | |
Joseph Wynn | fa00c4c9cf | |
Joseph Wynn | 4b75f67558 | |
Joseph Wynn | 307f3c6284 | |
Quinn | f3103be702 | |
Joseph Wynn | 5715734bde | |
Joseph Wynn | 8cb3c53dd7 | |
Joseph Wynn | 16ab99deac | |
Joseph Wynn | 91a540c266 | |
Joseph Wynn | 48c36e75b9 | |
Joseph Wynn | 9d6f549855 | |
Joseph Wynn | 4d90cd177e | |
Joseph Wynn | 3d7f0e609b | |
Joseph Wynn | 6444d327de | |
Arno Gourdol | b9791014de | |
Joseph Wynn | 6d323718cf | |
Joseph Wynn | 0153b9fb9e | |
Joseph Wynn | 6533035416 | |
Daniel Pietzsch | 855c3a70e4 | |
Joseph Wynn | bc61757f2a | |
Ken Salomon | 38e3b1f92f | |
Joseph Wynn | 3cf3bc7be3 | |
Joseph Wynn | d902ec743d | |
Joseph Wynn | c559bcced3 | |
Joseph Wynn | b76e2d3365 | |
Joseph Wynn | 1df929e20d | |
Joseph Wynn | 7a3dbf1ab9 | |
Christopher Peterson | ac86fb2440 | |
Christopher Peterson | aaaabbc2c0 | |
Joseph Wynn | 311f434ed7 | |
Joseph Wynn | b628a11925 | |
Bert Driehuis | cafec3c926 | |
Bert Driehuis | 826b5f715e | |
Joseph Wynn | c9da267bee | |
Joseph Wynn | aba1d58246 | |
Joseph Wynn | b1ac375f60 | |
Joseph Wynn | bd52112bae | |
Joseph Wynn | 66b0f3fce9 | |
Joseph Wynn | e334930825 | |
Jeric Bryle Sy Dy | 2ad615952e | |
Jeric Bryle Sy Dy | 93bb666bff | |
Joseph Wynn | 893486fb45 | |
Joseph Wynn | 3e4fac4132 | |
Joseph Wynn | a23bdf5895 | |
Joseph Wynn | 98a3b143af | |
Joseph Wynn | b16abdc43c | |
Joseph Wynn | 7ad3967c71 | |
Joseph Wynn | 73bd82d547 | |
Joseph Wynn | ffc51f648b | |
jameswood | db264444ac | |
Joseph Wynn | 0c342075c7 | |
Joseph Wynn | 00ded027ad | |
Joseph Wynn | 85b56541fb | |
Joseph Wynn | 746205e726 | |
Joseph Wynn | ba3db6eba7 | |
Joseph Wynn | fd041dc44a | |
Joseph Wynn | c8eb8c0c58 | |
Joseph Wynn | c2e3465a7e | |
Joseph Wynn | 8fa0543494 | |
Joseph Wynn | 804d30dbb5 | |
Joseph Wynn | d7451d2681 | |
Joseph Wynn | 03356da52d | |
Joseph Wynn | 8d962b2631 | |
Joseph Wynn | 39ee353912 | |
Joseph Wynn | dba32db868 | |
Joseph Wynn | 9a4f6dc9d0 | |
Joseph Wynn | 1d7273ec5a | |
Joseph Wynn | 854aa4cf00 | |
Joseph Wynn | 0d3f099057 | |
Joseph Wynn | 83358e79b5 | |
Joseph Wynn | 4de5db835d | |
Joseph Wynn | 6d569710b9 | |
Joseph Wynn | b47f12a1db | |
Joseph Wynn | 354f693afc | |
Joseph Wynn | a1a183c3d4 |
|
@ -0,0 +1 @@
|
||||||
|
features/test-site/* linguist-vendored
|
|
@ -0,0 +1,10 @@
|
||||||
|
daysUntilStale: 18
|
||||||
|
daysUntilClose: 3
|
||||||
|
staleLabel: stale
|
||||||
|
exemptLabels:
|
||||||
|
- pinned
|
||||||
|
markComment: >
|
||||||
|
This issue has been automatically marked as stale because it has not had
|
||||||
|
recent activity. It will be closed if no further activity occurs. Thank you
|
||||||
|
for your contributions.
|
||||||
|
closeComment: false
|
12
.travis.yml
12
.travis.yml
|
@ -1,10 +1,12 @@
|
||||||
sudo: false
|
sudo: false
|
||||||
|
dist: trusty
|
||||||
language: ruby
|
language: ruby
|
||||||
bundler_args: --without debug
|
bundler_args: --without debug
|
||||||
before_script: bundle exec jekyll --version
|
before_script: bundle exec jekyll --version
|
||||||
script: bundle exec rake rubocop features_with_coveralls
|
script: bundle exec rake features_with_coveralls
|
||||||
rvm:
|
rvm:
|
||||||
- 2.2
|
- '2.6'
|
||||||
- 2.1
|
- '2.5'
|
||||||
- 2.0
|
- '2.4'
|
||||||
- 1.9
|
- '2.3'
|
||||||
|
- '2.2'
|
||||||
|
|
12
Gemfile
12
Gemfile
|
@ -1,14 +1,12 @@
|
||||||
source 'https://rubygems.org/'
|
source 'https://rubygems.org/'
|
||||||
|
|
||||||
gemspec
|
gemspec
|
||||||
|
|
||||||
group :development do
|
group :development do
|
||||||
gem 'rake'
|
gem 'rake'
|
||||||
gem 'cucumber', '~> 2.4'
|
gem 'cucumber', '~> 3.1'
|
||||||
gem 'test-unit', '~> 3.1', require: false
|
gem 'test-unit', '~> 3.2'
|
||||||
gem 'rubocop', '~> 0.43', require: false
|
|
||||||
gem 'coveralls', require: false
|
|
||||||
|
|
||||||
platform :ruby_18, :ruby_19 do
|
gem 'simplecov', :require => false
|
||||||
gem 'simplecov', '>= 0.10', '< 0.12'
|
gem 'coveralls', :require => false
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2014 Joseph Wynn
|
Copyright (c) 2018 Joseph Wynn
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
270
README.md
270
README.md
|
@ -1,80 +1,53 @@
|
||||||
# Jekyll Responsive Images
|
# jekyll-responsive-image
|
||||||
|
|
||||||
Jekyll Responsive Images is a [Jekyll](http://jekyllrb.com/) plugin and utility for automatically resizing images. Its intended use is for sites which want to display responsive images using something like [`srcset`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Img#Specifications) or [Imager.js](https://github.com/BBC-News/Imager.js/).
|
A [Jekyll](http://jekyllrb.com/) plugin for automatically resizing images. Fully configurable and unopinionated, jekyll-responsive-image allows you to display responsive images however you like: using [`<img srcset>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Img#attr-srcset), [`<picture>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture), or [Imager.js](https://github.com/BBC-News/Imager.js/).
|
||||||
|
|
||||||
[![Build Status](https://img.shields.io/travis/wildlyinaccurate/jekyll-responsive-image.svg?style=flat-square)](https://travis-ci.org/wildlyinaccurate/jekyll-responsive-image)
|
[![Build Status](https://img.shields.io/travis/wildlyinaccurate/jekyll-responsive-image.svg?style=flat-square)](https://travis-ci.org/wildlyinaccurate/jekyll-responsive-image)
|
||||||
[![Coverage Status](https://img.shields.io/coveralls/wildlyinaccurate/jekyll-responsive-image.svg?style=flat-square)](https://coveralls.io/repos/github/wildlyinaccurate/jekyll-responsive-image/badge.svg?branch=master)
|
[![Coverage Status](https://img.shields.io/coveralls/wildlyinaccurate/jekyll-responsive-image.svg?style=flat-square)](https://coveralls.io/repos/github/wildlyinaccurate/jekyll-responsive-image/badge.svg?branch=master)
|
||||||
[![Dependency Status](https://img.shields.io/gemnasium/wildlyinaccurate/jekyll-responsive-images.svg?style=flat-square)](https://gemnasium.com/wildlyinaccurate/jekyll-responsive-images)
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
First, install the gem:
|
This plugin can be installed in three steps:
|
||||||
|
|
||||||
|
### 1. Install the gem
|
||||||
|
|
||||||
|
Either add `jekyll-responsive-image` to your Gemfile, or run the following command to install the gem:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ gem install jekyll-responsive_image
|
$ gem install jekyll-responsive-image
|
||||||
```
|
```
|
||||||
|
|
||||||
Then you can either add it to the `gems` section of your `_config.yml`:
|
Then you can either add `jekyll-responsive-image` to the `plugins` section of your `_config.yml`:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
gems: [jekyll/responsive_image]
|
plugins:
|
||||||
|
- jekyll-responsive-image
|
||||||
```
|
```
|
||||||
|
Note: If you are using a Jekyll version less than 3.5.0, use the `gems` key instead of `plugins`.
|
||||||
|
|
||||||
Or you can copy the contents of [`responsive_image.rb`](lib/jekyll/responsive_image.rb) into your `_plugins` directory.
|
Or you can copy the contents of [`responsive_image.rb`](lib/jekyll-responsive-image.rb) into your `_plugins` directory.
|
||||||
|
|
||||||
## Configuration
|
### 2. Create an image template file
|
||||||
|
|
||||||
An example configuration is below.
|
You will need to create a template in order to use the `responsive_image` and `responsive_image_block` tags. Normally the template lives in your `_includes/` directory. Not sure where to start? [Take a look at the sample templates](sample-templates).
|
||||||
|
|
||||||
|
For more advanced templates, see the [**Templates**](#templates) section below.
|
||||||
|
|
||||||
|
### 3. Configure the plugin
|
||||||
|
|
||||||
|
You **must** have a `responsive_image` block in your `_config.yml` for this plugin to work. At a minimum, your `responsive_image` configuration should have a template path and a list of sizes.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
responsive_image:
|
responsive_image:
|
||||||
# [Required]
|
|
||||||
# Path to the image template.
|
|
||||||
template: _includes/responsive-image.html
|
template: _includes/responsive-image.html
|
||||||
|
|
||||||
# [Optional, Default: 85]
|
|
||||||
# Quality to use when resizing images.
|
|
||||||
default_quality: 90
|
|
||||||
|
|
||||||
# [Optional, Default: []]
|
|
||||||
# An array of resize configuration objects. Each object must contain at least
|
|
||||||
# a `width` value.
|
|
||||||
sizes:
|
sizes:
|
||||||
- width: 480 # [Required] How wide the resized image will be.
|
- width: 320
|
||||||
quality: 80 # [Optional] Overrides default_quality for this size.
|
- width: 480
|
||||||
- width: 800
|
- width: 800
|
||||||
- width: 1400
|
|
||||||
quality: 90
|
|
||||||
|
|
||||||
# [Optional, Default: assets]
|
|
||||||
# The base directory where assets are stored. This is used to determine the
|
|
||||||
# `dirname` value in `output_path_format` below.
|
|
||||||
base_path: assets
|
|
||||||
|
|
||||||
# [Optional, Default: assets/resized/%{filename}-%{width}x%{height}.%{extension}]
|
|
||||||
# The template used when generating filenames for resized images. Must be a
|
|
||||||
# relative path.
|
|
||||||
#
|
|
||||||
# Parameters available are:
|
|
||||||
# %{dirname} Directory of the file relative to `base_path` (assets/sub/dir/some-file.jpg => sub/dir)
|
|
||||||
# %{basename} Basename of the file (assets/some-file.jpg => some-file.jpg)
|
|
||||||
# %{filename} Basename without the extension (assets/some-file.jpg => some-file)
|
|
||||||
# %{extension} Extension of the file (assets/some-file.jpg => jpg)
|
|
||||||
# %{width} Width of the resized image
|
|
||||||
# %{height} Height of the resized image
|
|
||||||
#
|
|
||||||
output_path_format: assets/resized/%{width}/%{basename}
|
|
||||||
|
|
||||||
# [Optional, Default: []]
|
|
||||||
# By default, only images referenced by the responsive_image and responsive_image_block
|
|
||||||
# tags are resized. Here you can set a list of paths or path globs to resize other
|
|
||||||
# images. This is useful for resizing images which will be referenced from stylesheets.
|
|
||||||
extra_images:
|
|
||||||
- assets/foo/bar.png
|
|
||||||
- assets/bgs/*.png
|
|
||||||
- assets/avatars/*.{jpeg,jpg}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
For a list of all the available configuration options, see the [**All configuration options**](#all-configuration-options) section below.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Replace your images with the `responsive_image` tag, specifying the path to the image in the `path` attribute.
|
Replace your images with the `responsive_image` tag, specifying the path to the image in the `path` attribute.
|
||||||
|
@ -114,65 +87,26 @@ You can use Liquid variables as attributes with the `responsive_image_block` tag
|
||||||
{% endresponsive_image_block %}
|
{% endresponsive_image_block %}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Template
|
## Templates
|
||||||
|
|
||||||
You will need to create a template in order to use the `responsive_image` tag. Below are some sample templates to get you started.
|
It's easy to build your own custom templates to render images however you want using the template variables provided by jekyll-responsive-image.
|
||||||
|
|
||||||
#### Responsive images with `srcset`
|
|
||||||
|
|
||||||
```twig
|
|
||||||
{% capture srcset %}
|
|
||||||
{% for i in resized %}
|
|
||||||
/{{ i.path }} {{ i.width }}w,
|
|
||||||
{% endfor %}
|
|
||||||
{% endcapture %}
|
|
||||||
|
|
||||||
<img src="/{{ path }}" alt="{{ alt }}" srcset="{{ srcset | strip_newlines }} /{{ original.path }} {{ original.width }}w">
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Responsive images with `<picture>`
|
|
||||||
|
|
||||||
```twig
|
|
||||||
<picture>
|
|
||||||
{% for i in resized %}
|
|
||||||
<source media="(min-width: {{ i.width }}px)" srcset="/{{ i.path }}">
|
|
||||||
{% endfor %}
|
|
||||||
<img src="/{{ path }}">
|
|
||||||
</picture>
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Responsive images using [Imager.js](https://github.com/BBC-News/Imager.js/)
|
|
||||||
|
|
||||||
> **Note:** This template assumes an `output_path_format` of `assets/resized/%{width}/%{basename}`
|
|
||||||
|
|
||||||
```twig
|
|
||||||
{% assign smallest = resized | sort: 'width' | first %}
|
|
||||||
|
|
||||||
<div class="responsive-image">
|
|
||||||
<img class="responsive-image__placeholder" src="/{{ smallest.path }}">
|
|
||||||
<div class="responsive-image__delayed" data-src="/assets/resized/{width}/{{ original.basename }}"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
new Imager('.responsive-image__delayed', {
|
|
||||||
availableWidths: [{{ resized | map: 'width' | join: ', ' }}]
|
|
||||||
onImagesReplaced: function() {
|
|
||||||
$('.responsive-image__placeholder').hide();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Template Variables
|
### Template Variables
|
||||||
|
|
||||||
The following variables are available in the template:
|
The following variables are available in the template:
|
||||||
|
|
||||||
| Variable | Type | Description |
|
| Variable | Type | Description |
|
||||||
|----------- |--------|------------------------------------------------------------------------------------------------------|
|
|------------|---------------|------------------------------------------------------------------------------------------------------|
|
||||||
| `path` | String | The path of the unmodified image. This is always the same as the `path` attribute passed to the tag. |
|
| `path` | String | The path of the unmodified image. This is always the same as the `path` attribute passed to the tag. |
|
||||||
| `resized` | Array | An array of all the resized images. Each image is an **Image Object**. |
|
| `resized` | Array<Object> | An array of all the resized images. Each image is an **Image Object**. |
|
||||||
| `original` | Object | An **Image Object** containing information about the original image. |
|
| `original` | Object | An **Image Object** containing information about the original image. |
|
||||||
| `*` | String | Any other attributes will be passed to the template verbatim as strings. |
|
| `*` | String | Any other attributes will be passed to the template verbatim as strings (see below). |
|
||||||
|
|
||||||
|
Any other attributes that are given to the `responsive_image` or `responsive_image_block` tags will be available in the template. For example the following tag will provide an `{{ alt }}` variable to the template:
|
||||||
|
|
||||||
|
```twig
|
||||||
|
{% responsive_image path: assets/my-file.jpg alt: "A description of the image" %}
|
||||||
|
```
|
||||||
|
|
||||||
#### Image Objects
|
#### Image Objects
|
||||||
|
|
||||||
|
@ -187,3 +121,135 @@ Image objects (like `original` and each object in `resized`) contain the followi
|
||||||
| `dirname` | String | Directory of the file relative to `base_path` (`assets/sub/dir/some-file.jpg` => `sub/dir`). |
|
| `dirname` | String | Directory of the file relative to `base_path` (`assets/sub/dir/some-file.jpg` => `sub/dir`). |
|
||||||
| `filename` | String | Basename without the extension (`assets/some-file.jpg` => `some-file`). |
|
| `filename` | String | Basename without the extension (`assets/some-file.jpg` => `some-file`). |
|
||||||
| `extension` | String | Extension of the file (`assets/some-file.jpg` => `jpg`). |
|
| `extension` | String | Extension of the file (`assets/some-file.jpg` => `jpg`). |
|
||||||
|
|
||||||
|
## All configuration options
|
||||||
|
|
||||||
|
A full list of all of the available configuration options is below.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
responsive_image:
|
||||||
|
# [Required]
|
||||||
|
# Path to the image template.
|
||||||
|
template: _includes/responsive-image.html
|
||||||
|
|
||||||
|
# [Optional, Default: 85]
|
||||||
|
# Quality to use when resizing images.
|
||||||
|
default_quality: 90
|
||||||
|
|
||||||
|
# [Optional, Default: []]
|
||||||
|
# An array of resize configuration objects. Each object must contain at least
|
||||||
|
# a `width` value.
|
||||||
|
sizes:
|
||||||
|
- width: 480 # [Required] How wide the resized image will be.
|
||||||
|
quality: 80 # [Optional] Overrides default_quality for this size.
|
||||||
|
- width: 800
|
||||||
|
- width: 1400
|
||||||
|
quality: 90
|
||||||
|
|
||||||
|
# [Optional, Default: false]
|
||||||
|
# Rotate resized images depending on their EXIF rotation attribute. Useful for
|
||||||
|
# working with JPGs directly from digital cameras and smartphones
|
||||||
|
auto_rotate: false
|
||||||
|
|
||||||
|
# [Optional, Default: false]
|
||||||
|
# Strip EXIF and other JPEG profiles. Helps to minimize JPEG size and win friends
|
||||||
|
# at Google PageSpeed.
|
||||||
|
strip: false
|
||||||
|
|
||||||
|
# [Optional, Default: assets]
|
||||||
|
# The base directory where assets are stored. This is used to determine the
|
||||||
|
# `dirname` value in `output_path_format` below.
|
||||||
|
base_path: assets
|
||||||
|
|
||||||
|
# [Optional, Default: assets/resized/%{filename}-%{width}x%{height}.%{extension}]
|
||||||
|
# The template used when generating filenames for resized images. Must be a
|
||||||
|
# relative path.
|
||||||
|
#
|
||||||
|
# Parameters available are:
|
||||||
|
# %{dirname} Directory of the file relative to `base_path` (assets/sub/dir/some-file.jpg => sub/dir)
|
||||||
|
# %{basename} Basename of the file (assets/some-file.jpg => some-file.jpg)
|
||||||
|
# %{filename} Basename without the extension (assets/some-file.jpg => some-file)
|
||||||
|
# %{extension} Extension of the file (assets/some-file.jpg => jpg)
|
||||||
|
# %{width} Width of the resized image
|
||||||
|
# %{height} Height of the resized image
|
||||||
|
#
|
||||||
|
output_path_format: assets/resized/%{width}/%{basename}
|
||||||
|
|
||||||
|
# [Optional, Default: true]
|
||||||
|
# Whether or not to save the generated assets into the source folder.
|
||||||
|
save_to_source: false
|
||||||
|
|
||||||
|
# [Optional, Default: false]
|
||||||
|
# Cache the result of {% responsive_image %} and {% responsive_image_block %}
|
||||||
|
# tags. See the "Caching" section of the README for more information.
|
||||||
|
cache: false
|
||||||
|
|
||||||
|
# [Optional, Default: []]
|
||||||
|
# By default, only images referenced by the responsive_image and responsive_image_block
|
||||||
|
# tags are resized. Here you can set a list of paths or path globs to resize other
|
||||||
|
# images. This is useful for resizing images which will be referenced from stylesheets.
|
||||||
|
extra_images:
|
||||||
|
- assets/foo/bar.png
|
||||||
|
- assets/bgs/*.png
|
||||||
|
- assets/avatars/*.{jpeg,jpg}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Error: Can't install RMagick
|
||||||
|
|
||||||
|
`jekyll-responsive-image` uses `rmagick` which is currently incompatible with ImageMagick 7. If you get an error like:
|
||||||
|
|
||||||
|
```
|
||||||
|
Can't install RMagick 2.16.0. Can't find MagickWand.h
|
||||||
|
```
|
||||||
|
|
||||||
|
Then you will need to install ImageMagick 6. If you are using Homebrew on Mac OS, this can be done with the following commands:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ brew uninstall imagemagick
|
||||||
|
$ brew install imagemagick@6 && brew link imagemagick@6 --force
|
||||||
|
```
|
||||||
|
|
||||||
|
## Caching
|
||||||
|
|
||||||
|
You may be able to speed up the build of large sites by enabling render caching. This is usually only effective when the same image is used many times, for example a header image that is rendered in every post.
|
||||||
|
|
||||||
|
The recommended way to enable caching is on an image-by-image basis, by adding `cache: true` to the tag:
|
||||||
|
|
||||||
|
```twig
|
||||||
|
{% responsive_image path: 'assets/my-file.jpg' cache: true %}
|
||||||
|
|
||||||
|
{% responsive_image_block %}
|
||||||
|
path: assets/my-file.jpg
|
||||||
|
cache: true
|
||||||
|
{% endresponsive_image_block %}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also enable it for all images by adding `cache: true` to your `_config.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
responsive_image:
|
||||||
|
cache: true
|
||||||
|
template: _includes/responsive-image.html
|
||||||
|
sizes:
|
||||||
|
- ...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
If you'd like to contribute to this repository, here's how you can set it up for development:
|
||||||
|
|
||||||
|
1. Fork this repository
|
||||||
|
2. Clone the fork to your local machine
|
||||||
|
3. Install [ImageMagick](http://www.imagemagick.org/) (if you haven't already)
|
||||||
|
4. Run `bundle install`
|
||||||
|
5. Run the tests like this: `cucumber`
|
||||||
|
|
||||||
|
If you'd like your Jekyll project to use your local fork directly, you can add the `:path` parameter to your gem command in the project's Gemfile:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
gem 'jekyll-responsive-image', :path => "/your/local/path/to/jekyll-responsive-image"
|
||||||
|
```
|
||||||
|
|
||||||
|
If you'd like your changes to be considered for the original repository, simply submit a pull request after you've made your changes. Please make sure all tests pass.
|
||||||
|
|
13
Rakefile
13
Rakefile
|
@ -1,5 +1,4 @@
|
||||||
require 'bundler'
|
require 'bundler'
|
||||||
require 'rubocop/rake_task'
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
Bundler.setup(:default, :development)
|
Bundler.setup(:default, :development)
|
||||||
|
@ -10,22 +9,20 @@ rescue Bundler::BundlerError => e
|
||||||
end
|
end
|
||||||
|
|
||||||
require 'rake'
|
require 'rake'
|
||||||
require 'jekyll/responsive_image/version'
|
require 'jekyll-responsive-image/version'
|
||||||
require 'cucumber/rake/task'
|
require 'cucumber/rake/task'
|
||||||
require 'coveralls/rake/task'
|
require 'coveralls/rake/task'
|
||||||
|
|
||||||
RuboCop::RakeTask.new
|
|
||||||
|
|
||||||
Cucumber::Rake::Task.new(:features)
|
Cucumber::Rake::Task.new(:features)
|
||||||
|
|
||||||
Coveralls::RakeTask.new
|
Coveralls::RakeTask.new
|
||||||
task :features_with_coveralls => [:features, 'coveralls:push']
|
task :features_with_coveralls => [:features, 'coveralls:push']
|
||||||
|
|
||||||
task :default => [:rubocop, :features]
|
task :default => [:features]
|
||||||
|
|
||||||
task :release do |t|
|
task :release do |t|
|
||||||
system "gem build jekyll-responsive_image.gemspec"
|
system "gem build jekyll-responsive-image.gemspec"
|
||||||
system "git tag v#{Jekyll::ResponsiveImage::VERSION} -a -m 'Tagged release of jekyll-responsive_image-#{Jekyll::ResponsiveImage::VERSION}.gem'"
|
system "git tag v#{Jekyll::ResponsiveImage::VERSION} -a -m 'Tagged release of jekyll-responsive-image-#{Jekyll::ResponsiveImage::VERSION}.gem'"
|
||||||
system "git push --tags"
|
system "git push --tags"
|
||||||
system "gem push jekyll-responsive_image-#{Jekyll::ResponsiveImage::VERSION}.gem"
|
system "gem push jekyll-responsive-image-#{Jekyll::ResponsiveImage::VERSION}.gem"
|
||||||
end
|
end
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,35 +1,38 @@
|
||||||
Feature: Extra image generation
|
Feature: Extra image generation
|
||||||
As a Jekyll user
|
Scenario: Specifying a single image and glob patterns
|
||||||
I want to resize images that aren't used in posts or pages
|
|
||||||
In order to use them in my stylesheets
|
|
||||||
|
|
||||||
Scenario: Resizing a single image
|
|
||||||
Given I have a responsive_image configuration with:
|
Given I have a responsive_image configuration with:
|
||||||
"""
|
"""
|
||||||
sizes:
|
sizes:
|
||||||
- width: 100
|
- width: 100
|
||||||
extra_images:
|
extra_images:
|
||||||
- assets/everybody-loves-jalapeño-pineapple-cornbread.png
|
- assets/everybody-loves-jalapeño-pineapple-cornbread.png
|
||||||
|
- assets/*.jpeg
|
||||||
"""
|
"""
|
||||||
|
|
||||||
And I have a file "index.html" with "Hello, world!"
|
And I have a file "index.html" with "Hello, world!"
|
||||||
When I run Jekyll
|
When I run Jekyll
|
||||||
Then the image "assets/resized/everybody-loves-jalapeño-pineapple-cornbread-100x50.png" should have the dimensions "100x50"
|
Then the image "assets/resized/everybody-loves-jalapeño-pineapple-cornbread-100x50.png" should have the dimensions "100x50"
|
||||||
|
And the image "assets/resized/progressive-100x50.jpeg" should have the dimensions "100x50"
|
||||||
And the file "_site/assets/resized/everybody-loves-jalapeño-pineapple-cornbread-100x50.png" should exist
|
And the file "_site/assets/resized/everybody-loves-jalapeño-pineapple-cornbread-100x50.png" should exist
|
||||||
|
And the file "_site/assets/resized/progressive-100x50.jpeg" should exist
|
||||||
|
|
||||||
Scenario: Using glob patterns
|
Scenario: Specifying a recursive glob pattern
|
||||||
Given I have a responsive_image configuration with:
|
Given I have a responsive_image configuration with:
|
||||||
"""
|
"""
|
||||||
sizes:
|
sizes:
|
||||||
- width: 100
|
- width: 100
|
||||||
extra_images:
|
extra_images:
|
||||||
- assets/*.png
|
- assets/**/*
|
||||||
"""
|
"""
|
||||||
|
|
||||||
And I have a file "index.html" with "Hello, world!"
|
And I have a file "index.html" with "Hello, world!"
|
||||||
When I run Jekyll
|
When I run Jekyll
|
||||||
Then the image "assets/resized/everybody-loves-jalapeño-pineapple-cornbread-100x50.png" should have the dimensions "100x50"
|
Then the image "assets/resized/everybody-loves-jalapeño-pineapple-cornbread-100x50.png" should have the dimensions "100x50"
|
||||||
|
And the image "assets/resized/exif-rotation-100x50.jpeg" should have the dimensions "100x50"
|
||||||
|
And the image "assets/resized/progressive-100x50.jpeg" should have the dimensions "100x50"
|
||||||
|
And the image "assets/resized/test-100x50.png" should have the dimensions "100x50"
|
||||||
And the file "_site/assets/resized/everybody-loves-jalapeño-pineapple-cornbread-100x50.png" should exist
|
And the file "_site/assets/resized/everybody-loves-jalapeño-pineapple-cornbread-100x50.png" should exist
|
||||||
|
And the file "_site/assets/resized/exif-rotation-100x50.jpeg" should exist
|
||||||
|
And the file "_site/assets/resized/progressive-100x50.jpeg" should exist
|
||||||
|
And the file "_site/assets/resized/test-100x50.png" should exist
|
||||||
|
|
||||||
Scenario: Honouring Jekyll 'source' configuration
|
Scenario: Honouring Jekyll 'source' configuration
|
||||||
Given I have copied my site to "sub-dir/my-site-copy"
|
Given I have copied my site to "sub-dir/my-site-copy"
|
||||||
|
@ -42,19 +45,8 @@ Feature: Extra image generation
|
||||||
extra_images:
|
extra_images:
|
||||||
- assets/*.png
|
- assets/*.png
|
||||||
"""
|
"""
|
||||||
|
|
||||||
And I have a file "index.html" with "Hello, world!"
|
And I have a file "index.html" with "Hello, world!"
|
||||||
When I run Jekyll
|
When I run Jekyll
|
||||||
Then the image "sub-dir/my-site-copy/assets/resized/everybody-loves-jalapeño-pineapple-cornbread-100x50.png" should have the dimensions "100x50"
|
Then the image "sub-dir/my-site-copy/assets/resized/everybody-loves-jalapeño-pineapple-cornbread-100x50.png" should have the dimensions "100x50"
|
||||||
And the file "_site/assets/resized/everybody-loves-jalapeño-pineapple-cornbread-100x50.png" should exist
|
And the file "_site/assets/resized/everybody-loves-jalapeño-pineapple-cornbread-100x50.png" should exist
|
||||||
|
And the file "_site/assets/resized/progressive-100x50.jpeg" should not exist
|
||||||
Scenario: No extra images
|
|
||||||
Given I have a responsive_image configuration with:
|
|
||||||
"""
|
|
||||||
sizes:
|
|
||||||
- width: 100
|
|
||||||
"""
|
|
||||||
|
|
||||||
And I have a file "index.html" with "Hello, world!"
|
|
||||||
When I run Jekyll
|
|
||||||
Then the file "assets/resized/everybody-loves-jalapeño-pineapple-cornbread-100x50.png" should not exist
|
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
Feature: Responsive image generation
|
Feature: Responsive image generation
|
||||||
As a Jekyll user
|
|
||||||
I want to generate responsive images
|
|
||||||
In order to use them on my pages
|
|
||||||
|
|
||||||
Scenario: Resizing images
|
Scenario: Resizing images
|
||||||
Given I have a responsive_image configuration with:
|
Given I have a responsive_image configuration with:
|
||||||
"""
|
"""
|
||||||
|
@ -10,7 +6,6 @@ Feature: Responsive image generation
|
||||||
sizes:
|
sizes:
|
||||||
- width: 100
|
- width: 100
|
||||||
"""
|
"""
|
||||||
|
|
||||||
And I have a file "index.html" with "{% responsive_image path: assets/everybody-loves-jalapeño-pineapple-cornbread.png alt: Foobar %}"
|
And I have a file "index.html" with "{% responsive_image path: assets/everybody-loves-jalapeño-pineapple-cornbread.png alt: Foobar %}"
|
||||||
When I run Jekyll
|
When I run Jekyll
|
||||||
Then the image "assets/resized/everybody-loves-jalapeño-pineapple-cornbread-100x50.png" should have the dimensions "100x50"
|
Then the image "assets/resized/everybody-loves-jalapeño-pineapple-cornbread-100x50.png" should have the dimensions "100x50"
|
||||||
|
@ -24,26 +19,36 @@ Feature: Responsive image generation
|
||||||
sizes:
|
sizes:
|
||||||
- width: 100
|
- width: 100
|
||||||
"""
|
"""
|
||||||
|
|
||||||
And I have a file "index.html" with:
|
And I have a file "index.html" with:
|
||||||
"""
|
"""
|
||||||
{% responsive_image path: assets/everybody-loves-jalapeño-pineapple-cornbread.png %}
|
{% responsive_image path: assets/everybody-loves-jalapeño-pineapple-cornbread.png %}
|
||||||
{% responsive_image path: assets/subdir/test.png %}
|
{% responsive_image path: assets/subdir/test.png %}
|
||||||
{% responsive_image path: assets/everybody-loves-jalapeño-pineapple-cornbread.png cache: true %}
|
{% responsive_image path: assets/everybody-loves-jalapeño-pineapple-cornbread.png cache: true %}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
When I run Jekyll
|
When I run Jekyll
|
||||||
Then the file "assets/resized/everybody-loves-jalapeño-pineapple-cornbread-100.png" should exist
|
Then the file "assets/resized/everybody-loves-jalapeño-pineapple-cornbread-100.png" should exist
|
||||||
And the file "_site/assets/resized/everybody-loves-jalapeño-pineapple-cornbread-100.png" should exist
|
And the file "_site/assets/resized/everybody-loves-jalapeño-pineapple-cornbread-100.png" should exist
|
||||||
And the file "assets/resized/subdir/test-100.png" should exist
|
And the file "assets/resized/subdir/test-100.png" should exist
|
||||||
And the file "_site/assets/resized/subdir/test-100.png" should exist
|
And the file "_site/assets/resized/subdir/test-100.png" should exist
|
||||||
|
|
||||||
|
Scenario: Honouring source image interlace mode
|
||||||
|
Given I have a responsive_image configuration with:
|
||||||
|
"""
|
||||||
|
template: _includes/responsive-image.html
|
||||||
|
sizes:
|
||||||
|
- width: 100
|
||||||
|
"""
|
||||||
|
And I have a file "index.html" with "{% responsive_image path: assets/progressive.jpeg %}"
|
||||||
|
When I run Jekyll
|
||||||
|
Then the image "assets/resized/progressive-100x50.jpeg" should be interlaced
|
||||||
|
|
||||||
Scenario: Honouring Jekyll 'source' configuration
|
Scenario: Honouring Jekyll 'source' configuration
|
||||||
Given I have copied my site to "my-site-copy/src"
|
Given I have copied my site to "my-site-copy/src"
|
||||||
And I have a configuration with:
|
And I have a configuration with:
|
||||||
"""
|
"""
|
||||||
source: my-site-copy/src
|
source: my-site-copy/src
|
||||||
responsive_image:
|
responsive_image:
|
||||||
|
base_path: assets
|
||||||
template: _includes/responsive-image.html
|
template: _includes/responsive-image.html
|
||||||
output_path_format: assets/resized/%{dirname}/%{width}/%{basename}
|
output_path_format: assets/resized/%{dirname}/%{width}/%{basename}
|
||||||
sizes:
|
sizes:
|
||||||
|
@ -51,5 +56,64 @@ Feature: Responsive image generation
|
||||||
"""
|
"""
|
||||||
And I have a file "my-site-copy/src/index.html" with "{% responsive_image path: assets/subdir/test.png %}"
|
And I have a file "my-site-copy/src/index.html" with "{% responsive_image path: assets/subdir/test.png %}"
|
||||||
When I run Jekyll
|
When I run Jekyll
|
||||||
Then the image "my-site-copy/src/assets/resized/subdir/test-100x50.png" should have the dimensions "100x50"
|
Then the image "my-site-copy/src/assets/resized/subdir/100/test.png" should have the dimensions "100x50"
|
||||||
And the file "_site/assets/resized/subdir/test-100x50.png" should exist
|
And the file "_site/assets/resized/subdir/100/test.png" should exist
|
||||||
|
|
||||||
|
Scenario: Images can be auto-rotated based on EXIF rotation
|
||||||
|
Given I have a responsive_image configuration with:
|
||||||
|
"""
|
||||||
|
template: _includes/responsive-image.html
|
||||||
|
sizes:
|
||||||
|
- width: 100
|
||||||
|
auto_rotate: true
|
||||||
|
"""
|
||||||
|
And I have a file "index.html" with "{% responsive_image path: assets/exif-rotation.jpeg %}"
|
||||||
|
When I run Jekyll
|
||||||
|
Then the file "_site/assets/resized/exif-rotation-100x200.jpeg" should exist
|
||||||
|
|
||||||
|
Scenario: Images aren't auto-rotated by default
|
||||||
|
Given I have a responsive_image configuration with:
|
||||||
|
"""
|
||||||
|
template: _includes/responsive-image.html
|
||||||
|
sizes:
|
||||||
|
- width: 100
|
||||||
|
"""
|
||||||
|
And I have a file "index.html" with:
|
||||||
|
"""
|
||||||
|
{% responsive_image path: assets/exif-rotation.jpeg %}
|
||||||
|
{% responsive_image path: assets/progressive.jpeg %}
|
||||||
|
"""
|
||||||
|
When I run Jekyll
|
||||||
|
Then the file "_site/assets/resized/exif-rotation-100x50.jpeg" should exist
|
||||||
|
Then the file "_site/assets/resized/progressive-100x50.jpeg" should exist
|
||||||
|
|
||||||
|
Scenario: Images should not be stripped of EXIF info by default
|
||||||
|
Given I have a responsive_image configuration with:
|
||||||
|
"""
|
||||||
|
template: _includes/responsive-image.html
|
||||||
|
sizes:
|
||||||
|
- width: 100
|
||||||
|
"""
|
||||||
|
And I have a file "index.html" with:
|
||||||
|
"""
|
||||||
|
{% responsive_image path: assets/exif-rotation.jpeg %}
|
||||||
|
"""
|
||||||
|
When I run Jekyll
|
||||||
|
Then the file "_site/assets/resized/exif-rotation-100x50.jpeg" should exist
|
||||||
|
Then the image "_site/assets/resized/exif-rotation-100x50.jpeg" should have an EXIF orientation
|
||||||
|
|
||||||
|
Scenario: Images can be stripped of EXIF info
|
||||||
|
Given I have a responsive_image configuration with:
|
||||||
|
"""
|
||||||
|
template: _includes/responsive-image.html
|
||||||
|
sizes:
|
||||||
|
- width: 100
|
||||||
|
strip: true
|
||||||
|
"""
|
||||||
|
And I have a file "index.html" with:
|
||||||
|
"""
|
||||||
|
{% responsive_image path: assets/exif-rotation.jpeg %}
|
||||||
|
"""
|
||||||
|
When I run Jekyll
|
||||||
|
Then the file "_site/assets/resized/exif-rotation-100x50.jpeg" should exist
|
||||||
|
Then the image "_site/assets/resized/exif-rotation-100x50.jpeg" should have no EXIF orientation
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
Feature: Image hashes inside responsive image templates
|
||||||
|
Scenario: Using the {% responsive_image %} tag
|
||||||
|
Given I have copied my site to "my-site-copy/src"
|
||||||
|
And I have a configuration with:
|
||||||
|
"""
|
||||||
|
source: my-site-copy/src
|
||||||
|
responsive_image:
|
||||||
|
template: _includes/hash.html
|
||||||
|
output_path_format: assets/resized/%{dirname}/%{width}/%{basename}
|
||||||
|
sizes:
|
||||||
|
- width: 100
|
||||||
|
"""
|
||||||
|
And I have a file "my-site-copy/src/index.html" with "{% responsive_image path: assets/subdir/test.png %}"
|
||||||
|
When I run Jekyll
|
||||||
|
Then the file "_site/index.html" should contain:
|
||||||
|
"""
|
||||||
|
path: assets/subdir/test.png
|
||||||
|
width: 300
|
||||||
|
height: 150
|
||||||
|
basename: test.png
|
||||||
|
dirname: subdir
|
||||||
|
filename: test
|
||||||
|
extension: png
|
||||||
|
|
||||||
|
path: assets/resized/subdir/100/test.png
|
||||||
|
width: 100
|
||||||
|
height: 50
|
||||||
|
basename: test.png
|
||||||
|
dirname: resized/subdir/100
|
||||||
|
filename: test
|
||||||
|
extension: png
|
||||||
|
"""
|
|
@ -0,0 +1,12 @@
|
||||||
|
Feature: General plugin usage
|
||||||
|
Scenario: No config at all
|
||||||
|
Given I have no configuration
|
||||||
|
When I run Jekyll
|
||||||
|
Then there should be no errors
|
||||||
|
|
||||||
|
Scenario: Config with empty responsive_image block
|
||||||
|
Given I have a responsive_image configuration with:
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
When I run Jekyll
|
||||||
|
Then there should be no errors
|
|
@ -1,19 +1,27 @@
|
||||||
Feature: Jekyll responsive_image_block tag
|
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
|
Scenario: Simple image tag
|
||||||
Given I have a responsive_image configuration with "template" set to "_includes/responsive-image.html"
|
Given I have a responsive_image configuration with "template" set to "_includes/responsive-image.html"
|
||||||
And I have a file "index.html" with:
|
And I have a file "index.html" with:
|
||||||
"""
|
"""
|
||||||
{% assign path = 'assets/everybody-loves-jalapeño-pineapple-cornbread.png' %}
|
{% assign path = 'assets/everybody-loves-jalapeño-pineapple-cornbread.png' %}
|
||||||
{% assign alt = 'Lorem ipsum' %}
|
|
||||||
|
|
||||||
{% responsive_image_block %}
|
{% responsive_image_block %}
|
||||||
path: {{ path }}
|
path: {{ path }}
|
||||||
title: Magic rainbow adventure!
|
title: Magic rainbow adventure!
|
||||||
alt: {{ alt }}
|
alt: Lorem ipsum
|
||||||
|
{% endresponsive_image_block %}
|
||||||
|
"""
|
||||||
|
When I run Jekyll
|
||||||
|
Then I should see "<img alt=\"Lorem ipsum\" src=\"/assets/everybody-loves-jalapeño-pineapple-cornbread.png\" title=\"Magic rainbow adventure!\"" in "_site/index.html"
|
||||||
|
|
||||||
|
Scenario: Tabs for indentation
|
||||||
|
Given I have a responsive_image configuration with "template" set to "_includes/responsive-image.html"
|
||||||
|
And I have a file "index.html" with:
|
||||||
|
"""
|
||||||
|
{% assign path = 'assets/everybody-loves-jalapeño-pineapple-cornbread.png' %}
|
||||||
|
{% responsive_image_block %}
|
||||||
|
path: {{ path }}
|
||||||
|
title: Magic rainbow adventure!
|
||||||
|
alt: Lorem ipsum
|
||||||
{% endresponsive_image_block %}
|
{% endresponsive_image_block %}
|
||||||
"""
|
"""
|
||||||
When I run Jekyll
|
When I run Jekyll
|
||||||
|
@ -41,7 +49,6 @@ Feature: Jekyll responsive_image_block tag
|
||||||
"""
|
"""
|
||||||
{% assign path = 'assets/everybody-loves-jalapeño-pineapple-cornbread.png' %}
|
{% assign path = 'assets/everybody-loves-jalapeño-pineapple-cornbread.png' %}
|
||||||
{% assign alt = 'Lorem ipsum' %}
|
{% assign alt = 'Lorem ipsum' %}
|
||||||
|
|
||||||
{% responsive_image_block %}
|
{% responsive_image_block %}
|
||||||
path: {{ path }}
|
path: {{ path }}
|
||||||
|
|
||||||
|
@ -63,4 +70,4 @@ Feature: Jekyll responsive_image_block tag
|
||||||
path: {{ path }}
|
path: {{ path }}
|
||||||
{% endresponsive_image_block %}
|
{% endresponsive_image_block %}
|
||||||
"""
|
"""
|
||||||
Then Jekyll should throw a "SyntaxError"
|
Then Jekyll should throw a "Magick::ImageMagickError"
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
Feature: Jekyll responsive_image tag
|
Feature: Jekyll responsive_image tag
|
||||||
As a Jekyll template developer
|
|
||||||
I want to include responsive images in my page
|
|
||||||
In order to best cater for devices of all sizes
|
|
||||||
|
|
||||||
Scenario: Simple image tag
|
Scenario: Simple image tag
|
||||||
Given I have a responsive_image configuration with "template" set to "_includes/responsive-image.html"
|
Given I have a responsive_image configuration with "template" set to "_includes/responsive-image.html"
|
||||||
And I have a file "index.html" with "{% responsive_image path: assets/everybody-loves-jalapeño-pineapple-cornbread.png alt: Foobar %}"
|
And I have a file "index.html" with "{% responsive_image path: assets/everybody-loves-jalapeño-pineapple-cornbread.png alt: Foobar %}"
|
||||||
|
@ -22,10 +18,7 @@ Feature: Jekyll responsive_image tag
|
||||||
|
|
||||||
Scenario: Adding custom attributes
|
Scenario: Adding custom attributes
|
||||||
Given I have a responsive_image configuration with "template" set to "_includes/responsive-image.html"
|
Given I have a responsive_image configuration with "template" set to "_includes/responsive-image.html"
|
||||||
And I have a file "index.html" with:
|
And I have a file "index.html" with "{% responsive_image path: assets/everybody-loves-jalapeño-pineapple-cornbread.png alt: 'Foobar bazbar' title: 'Lorem Ipsum' %}"
|
||||||
"""
|
|
||||||
{% responsive_image path: assets/everybody-loves-jalapeño-pineapple-cornbread.png alt: 'Foobar bazbar' title: "Lorem Ipsum" %}
|
|
||||||
"""
|
|
||||||
When I run Jekyll
|
When I run Jekyll
|
||||||
Then I should see "<img alt=\"Foobar bazbar\" src=\"/assets/everybody-loves-jalapeño-pineapple-cornbread.png\" title=\"Lorem Ipsum\"" in "_site/index.html"
|
Then I should see "<img alt=\"Foobar bazbar\" src=\"/assets/everybody-loves-jalapeño-pineapple-cornbread.png\" title=\"Lorem Ipsum\"" in "_site/index.html"
|
||||||
|
|
||||||
|
@ -48,9 +41,6 @@ Feature: Jekyll responsive_image tag
|
||||||
Then I should see "<img alt=\"\" src=\"/assets/subdir/test.png\"" in "_site/index.html"
|
Then I should see "<img alt=\"\" src=\"/assets/subdir/test.png\"" in "_site/index.html"
|
||||||
And I should see "/assets/resized/test-100x50.png 100w,/assets/resized/test-200x100.png 200w,/assets/subdir/test.png 300w" in "_site/index.html"
|
And I should see "/assets/resized/test-100x50.png 100w,/assets/resized/test-200x100.png 200w,/assets/subdir/test.png 300w" in "_site/index.html"
|
||||||
|
|
||||||
And the file "assets/resized/test-100x50.png" should exist
|
|
||||||
And the file "assets/resized/test-200x100.png" should exist
|
|
||||||
|
|
||||||
Scenario: Overriding the template
|
Scenario: Overriding the template
|
||||||
Given I have a responsive_image configuration with:
|
Given I have a responsive_image configuration with:
|
||||||
"""
|
"""
|
||||||
|
@ -58,11 +48,10 @@ Feature: Jekyll responsive_image tag
|
||||||
sizes:
|
sizes:
|
||||||
- width: 50
|
- width: 50
|
||||||
- width: 100
|
- width: 100
|
||||||
- width: 150
|
|
||||||
"""
|
"""
|
||||||
And I have a file "index.html" with "{% responsive_image path: assets/everybody-loves-jalapeño-pineapple-cornbread.png template: _includes/custom-template.html %}"
|
And I have a file "index.html" with "{% responsive_image path: assets/everybody-loves-jalapeño-pineapple-cornbread.png template: _includes/custom-template.html %}"
|
||||||
When I run Jekyll
|
When I run Jekyll
|
||||||
Then I should see "[50, 100, 150]" in "_site/index.html"
|
Then I should see "[50, 100]" in "_site/index.html"
|
||||||
|
|
||||||
Scenario: Overriding the generated filenames
|
Scenario: Overriding the generated filenames
|
||||||
Given I have a responsive_image configuration with:
|
Given I have a responsive_image configuration with:
|
||||||
|
@ -75,5 +64,3 @@ Feature: Jekyll responsive_image tag
|
||||||
And I have a file "index.html" with "{% responsive_image path: assets/everybody-loves-jalapeño-pineapple-cornbread.png %}"
|
And I have a file "index.html" with "{% responsive_image path: assets/everybody-loves-jalapeño-pineapple-cornbread.png %}"
|
||||||
When I run Jekyll
|
When I run Jekyll
|
||||||
Then I should see "/assets/everybody-loves-jalapeño-pineapple-cornbread.png-resized/100/everybody-loves-jalapeño-pineapple-cornbread-50.png 100w" in "_site/index.html"
|
Then I should see "/assets/everybody-loves-jalapeño-pineapple-cornbread.png-resized/100/everybody-loves-jalapeño-pineapple-cornbread-50.png 100w" in "_site/index.html"
|
||||||
And the file "assets/everybody-loves-jalapeño-pineapple-cornbread.png-resized/100/everybody-loves-jalapeño-pineapple-cornbread-50.png" should exist
|
|
||||||
And the file "_site/assets/everybody-loves-jalapeño-pineapple-cornbread.png-resized/100/everybody-loves-jalapeño-pineapple-cornbread-50.png" should exist
|
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
Feature: Save to source
|
||||||
|
Scenario: Resized images are saved to the source directory by default
|
||||||
|
Given I have a responsive_image configuration with:
|
||||||
|
"""
|
||||||
|
sizes:
|
||||||
|
- width: 100
|
||||||
|
extra_images:
|
||||||
|
- assets/everybody-loves-jalapeño-pineapple-cornbread.png
|
||||||
|
"""
|
||||||
|
And I have a file "index.html" with "Hello, world!"
|
||||||
|
When I run Jekyll
|
||||||
|
Then the file "assets/resized/everybody-loves-jalapeño-pineapple-cornbread-100x50.png" should exist
|
||||||
|
And the file "_site/assets/resized/everybody-loves-jalapeño-pineapple-cornbread-100x50.png" should exist
|
||||||
|
|
||||||
|
Scenario: Resized images can be saved to the destination directory only with save_to_source: false
|
||||||
|
Given I have a responsive_image configuration with:
|
||||||
|
"""
|
||||||
|
save_to_source: false
|
||||||
|
sizes:
|
||||||
|
- width: 100
|
||||||
|
extra_images:
|
||||||
|
- assets/everybody-loves-jalapeño-pineapple-cornbread.png
|
||||||
|
- assets/*.jpeg
|
||||||
|
"""
|
||||||
|
And I have a file "index.html" with "Hello, world!"
|
||||||
|
When I run Jekyll
|
||||||
|
Then the file "assets/resized/everybody-loves-jalapeño-pineapple-cornbread-100x50.png" should not exist
|
||||||
|
But the file "_site/assets/resized/everybody-loves-jalapeño-pineapple-cornbread-100x50.png" should exist
|
|
@ -6,6 +6,10 @@ Then /^Jekyll should throw a "(.+)"$/ do |error_class|
|
||||||
assert_raise(Object.const_get(error_class)) { run_jekyll }
|
assert_raise(Object.const_get(error_class)) { run_jekyll }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Then /^there should be no errors$/ do
|
||||||
|
# Implicit pass
|
||||||
|
end
|
||||||
|
|
||||||
Given /^I have copied my site to "(.+)"$/ do |path|
|
Given /^I have copied my site to "(.+)"$/ do |path|
|
||||||
new_site_dir = File.join(TEST_DIR, path)
|
new_site_dir = File.join(TEST_DIR, path)
|
||||||
|
|
||||||
|
@ -16,6 +20,10 @@ Given /^I have copied my site to "(.+)"$/ do |path|
|
||||||
.each { |f| FileUtils.mv(f, new_site_dir) }
|
.each { |f| FileUtils.mv(f, new_site_dir) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Given /^I have no configuration$/ do
|
||||||
|
write_file('_config.yml', '')
|
||||||
|
end
|
||||||
|
|
||||||
Given /^I have a configuration with:$/ do |config|
|
Given /^I have a configuration with:$/ do |config|
|
||||||
write_file('_config.yml', config)
|
write_file('_config.yml', config)
|
||||||
end
|
end
|
||||||
|
@ -41,6 +49,10 @@ Then /^I should see "(.+)" in "(.*)"$/ do |text, file|
|
||||||
assert contents.inspect.include?(text), "Expected to find #{text.inspect} in #{contents.inspect}"
|
assert contents.inspect.include?(text), "Expected to find #{text.inspect} in #{contents.inspect}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Then /^the file "(.+)" should contain:$/ do |file, contents|
|
||||||
|
assert_equal contents.strip, File.open(file).readlines.join.strip
|
||||||
|
end
|
||||||
|
|
||||||
Then /^the file "(.+)" should exist$/ do |path|
|
Then /^the file "(.+)" should exist$/ do |path|
|
||||||
assert File.exist?(path)
|
assert File.exist?(path)
|
||||||
end
|
end
|
||||||
|
@ -55,6 +67,24 @@ Then /^the image "(.+)" should have the dimensions "(\d+)x(\d+)"$/ do |path, wid
|
||||||
img.destroy!
|
img.destroy!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Then /^the image "(.+)" should be interlaced$/ do |path|
|
||||||
|
img = Magick::Image::read(path).first
|
||||||
|
assert_equal Magick::JPEGInterlace, img.interlace
|
||||||
|
img.destroy!
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^the image "(.+)" should have an EXIF orientation$/ do |path|
|
||||||
|
img = Magick::Image::read(path).first
|
||||||
|
assert_not_equal img.orientation.to_i, 0
|
||||||
|
img.destroy!
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^the image "(.+)" should have no EXIF orientation$/ do |path|
|
||||||
|
img = Magick::Image::read(path).first
|
||||||
|
assert_equal img.orientation.to_i, 0
|
||||||
|
img.destroy!
|
||||||
|
end
|
||||||
|
|
||||||
def write_file(path, contents)
|
def write_file(path, contents)
|
||||||
File.open(path, 'w') do |f|
|
File.open(path, 'w') do |f|
|
||||||
f.write(contents)
|
f.write(contents)
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
if ENV['CI']
|
require 'simplecov'
|
||||||
require 'coveralls'
|
require 'coveralls'
|
||||||
Coveralls.wear!
|
|
||||||
end
|
formatters = [SimpleCov::Formatter::HTMLFormatter]
|
||||||
|
formatters << Coveralls::SimpleCov::Formatter if ENV['CI']
|
||||||
|
|
||||||
|
SimpleCov.formatters = formatters
|
||||||
|
SimpleCov.start
|
||||||
|
|
||||||
require 'test/unit/assertions'
|
require 'test/unit/assertions'
|
||||||
require 'jekyll/responsive_image'
|
require 'jekyll-responsive-image'
|
||||||
|
|
||||||
TEST_DIR = File.join('/', 'tmp', 'jekyll')
|
TEST_DIR = File.join('/', 'tmp', 'jekyll')
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
path: {{ original.path }}
|
||||||
|
width: {{ original.width }}
|
||||||
|
height: {{ original.height }}
|
||||||
|
basename: {{ original.basename }}
|
||||||
|
dirname: {{ original.dirname }}
|
||||||
|
filename: {{ original.filename }}
|
||||||
|
extension: {{ original.extension }}
|
||||||
|
{% for i in resized %}
|
||||||
|
path: {{ i.path }}
|
||||||
|
width: {{ i.width }}
|
||||||
|
height: {{ i.height }}
|
||||||
|
basename: {{ i.basename }}
|
||||||
|
dirname: {{ i.dirname }}
|
||||||
|
filename: {{ i.filename }}
|
||||||
|
extension: {{ i.extension }}
|
||||||
|
{% endfor %}
|
|
@ -1 +1,3 @@
|
||||||
|
{% assign largest = resized | sort: 'width' | last %}
|
||||||
|
|
||||||
<img alt="{{ alt }}" src="/{{ original.path }}" title="{{ title }}" srcset="{% for i in resized %}/{{ i.path }} {{ i.width }}w,{% endfor %}/{{ original.path }} {{ original.width }}w">
|
<img alt="{{ alt }}" src="/{{ original.path }}" title="{{ title }}" srcset="{% for i in resized %}/{{ i.path }} {{ i.width }}w,{% endfor %}/{{ original.path }} {{ original.width }}w">
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 5.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.9 KiB |
|
@ -0,0 +1,27 @@
|
||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
lib = File.expand_path('../lib/', __FILE__)
|
||||||
|
$:.unshift lib unless $:.include?(lib)
|
||||||
|
|
||||||
|
require 'jekyll-responsive-image/version'
|
||||||
|
|
||||||
|
Gem::Specification.new do |spec|
|
||||||
|
spec.name = 'jekyll-responsive-image'
|
||||||
|
spec.version = Jekyll::ResponsiveImage::VERSION
|
||||||
|
spec.authors = ['Joseph Wynn']
|
||||||
|
spec.email = ['joseph@wildlyinaccurate.com']
|
||||||
|
spec.summary = 'Responsive image management for Jekyll'
|
||||||
|
spec.homepage = 'https://github.com/wildlyinaccurate/jekyll-responsive-image'
|
||||||
|
spec.licenses = ['MIT']
|
||||||
|
spec.description = %q{
|
||||||
|
Highly configurable Jekyll plugin for managing responsive images. Automatically
|
||||||
|
resizes images and provides a Liquid template tag for loading the images with
|
||||||
|
picture, img srcset, Imager.js, etc.
|
||||||
|
}
|
||||||
|
|
||||||
|
spec.files = `git ls-files -z lib/`.split("\u0000")
|
||||||
|
spec.executables = []
|
||||||
|
spec.require_paths = ['lib']
|
||||||
|
|
||||||
|
spec.add_runtime_dependency 'jekyll', ['>= 2.0', "< 5.0"]
|
||||||
|
spec.add_runtime_dependency 'rmagick', ['>= 2.0', '< 5.0']
|
||||||
|
end
|
|
@ -1,32 +0,0 @@
|
||||||
# -*- encoding: utf-8 -*-
|
|
||||||
lib = File.expand_path('../lib/', __FILE__)
|
|
||||||
$:.unshift lib unless $:.include?(lib)
|
|
||||||
|
|
||||||
require 'jekyll/responsive_image/version'
|
|
||||||
|
|
||||||
Gem::Specification.new do |spec|
|
|
||||||
spec.name = 'jekyll-responsive_image'
|
|
||||||
spec.version = Jekyll::ResponsiveImage::VERSION
|
|
||||||
spec.authors = ['Joseph Wynn']
|
|
||||||
spec.email = ['joseph@wildlyinaccurate.com']
|
|
||||||
spec.summary = 'Responsive images for Jekyll via srcset'
|
|
||||||
spec.homepage = 'https://github.com/wildlyinaccurate/jekyll-responsive-image'
|
|
||||||
spec.licenses = ['MIT']
|
|
||||||
spec.description = %q{
|
|
||||||
Jekyll Responsive Images is a Jekyll plugin and utility for automatically resizing images.
|
|
||||||
Its intended use is for sites which want to display responsive images using something like srcset or Imager.js.
|
|
||||||
}
|
|
||||||
|
|
||||||
spec.files = `git ls-files -z lib/`.split("\u0000")
|
|
||||||
spec.executables = []
|
|
||||||
spec.require_paths = ['lib']
|
|
||||||
|
|
||||||
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0.0')
|
|
||||||
max_jekyll_version = '3.0'
|
|
||||||
else
|
|
||||||
max_jekyll_version = '4.0'
|
|
||||||
end
|
|
||||||
|
|
||||||
spec.add_runtime_dependency 'jekyll', ['>= 2.0', "< #{max_jekyll_version}"]
|
|
||||||
spec.add_runtime_dependency 'rmagick', ['>= 2.0', '< 3.0']
|
|
||||||
end
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
require 'fileutils'
|
||||||
|
require 'yaml'
|
||||||
|
|
||||||
|
require 'jekyll'
|
||||||
|
require 'rmagick'
|
||||||
|
|
||||||
|
require 'jekyll-responsive-image/version'
|
||||||
|
require 'jekyll-responsive-image/config'
|
||||||
|
require 'jekyll-responsive-image/utils'
|
||||||
|
require 'jekyll-responsive-image/render_cache'
|
||||||
|
require 'jekyll-responsive-image/image_processor'
|
||||||
|
require 'jekyll-responsive-image/resize_handler'
|
||||||
|
require 'jekyll-responsive-image/renderer'
|
||||||
|
require 'jekyll-responsive-image/tag'
|
||||||
|
require 'jekyll-responsive-image/block'
|
||||||
|
require 'jekyll-responsive-image/extra_image_generator'
|
||||||
|
|
||||||
|
Liquid::Template.register_tag('responsive_image', Jekyll::ResponsiveImage::Tag)
|
||||||
|
Liquid::Template.register_tag('responsive_image_block', Jekyll::ResponsiveImage::Block)
|
|
@ -0,0 +1,18 @@
|
||||||
|
module Jekyll
|
||||||
|
module ResponsiveImage
|
||||||
|
class Block < Liquid::Block
|
||||||
|
include Jekyll::ResponsiveImage::Utils
|
||||||
|
|
||||||
|
def render(context)
|
||||||
|
content = super
|
||||||
|
|
||||||
|
if content.include?("\t")
|
||||||
|
content = content.lines.map {|line| line.gsub(/\G[\t ]/, " ")}.join("\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
attributes = YAML.load(content)
|
||||||
|
Renderer.new(context.registers[:site], attributes).render_responsive_image
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,37 @@
|
||||||
|
module Jekyll
|
||||||
|
module ResponsiveImage
|
||||||
|
class Config
|
||||||
|
DEFAULTS = {
|
||||||
|
'default_quality' => 85,
|
||||||
|
'base_path' => 'assets',
|
||||||
|
'output_path_format' => 'assets/resized/%{filename}-%{width}x%{height}.%{extension}',
|
||||||
|
'sizes' => [],
|
||||||
|
'extra_images' => [],
|
||||||
|
'auto_rotate' => false,
|
||||||
|
'save_to_source' => true,
|
||||||
|
'cache' => false,
|
||||||
|
'strip' => false
|
||||||
|
}
|
||||||
|
|
||||||
|
def initialize(site)
|
||||||
|
@site = site
|
||||||
|
end
|
||||||
|
|
||||||
|
def valid_config(config)
|
||||||
|
config.has_key?('responsive_image') && config['responsive_image'].is_a?(Hash)
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_h
|
||||||
|
config = {}
|
||||||
|
|
||||||
|
if valid_config(@site.config)
|
||||||
|
config = @site.config['responsive_image']
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
DEFAULTS.merge(config)
|
||||||
|
.merge(site_source: @site.source, site_dest: @site.dest)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,25 @@
|
||||||
|
module Jekyll
|
||||||
|
module ResponsiveImage
|
||||||
|
class ExtraImageGenerator < Jekyll::Generator
|
||||||
|
include Jekyll::ResponsiveImage::Utils
|
||||||
|
include FileTest
|
||||||
|
|
||||||
|
def generate(site)
|
||||||
|
config = Config.new(site).to_h
|
||||||
|
site_source = Pathname.new(site.source)
|
||||||
|
|
||||||
|
config['extra_images'].each do |pathspec|
|
||||||
|
Dir.glob(site.in_source_dir(pathspec)) do |image_path|
|
||||||
|
if FileTest.file?(image_path)
|
||||||
|
path = Pathname.new(image_path)
|
||||||
|
relative_image_path = path.relative_path_from(site_source)
|
||||||
|
|
||||||
|
result = ImageProcessor.process(relative_image_path, config)
|
||||||
|
result[:resized].each { |image| keep_resized_image!(site, image) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,24 @@
|
||||||
|
module Jekyll
|
||||||
|
module ResponsiveImage
|
||||||
|
class ImageProcessor
|
||||||
|
include ResponsiveImage::Utils
|
||||||
|
|
||||||
|
def process(image_path, config)
|
||||||
|
absolute_image_path = File.expand_path(image_path.to_s, config[:site_source])
|
||||||
|
|
||||||
|
Jekyll.logger.warn "Invalid image path specified: #{image_path.inspect}" unless File.file?(absolute_image_path)
|
||||||
|
|
||||||
|
resize_handler = ResizeHandler.new(absolute_image_path, config)
|
||||||
|
|
||||||
|
{
|
||||||
|
original: image_hash(config, image_path, resize_handler.original_image.columns, resize_handler.original_image.rows),
|
||||||
|
resized: resize_handler.resize_image,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.process(image_path, config)
|
||||||
|
self.new.process(image_path, config)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,41 @@
|
||||||
|
module Jekyll
|
||||||
|
module ResponsiveImage
|
||||||
|
class Renderer
|
||||||
|
include Jekyll::ResponsiveImage::Utils
|
||||||
|
|
||||||
|
def initialize(site, attributes)
|
||||||
|
@site = site
|
||||||
|
@attributes = attributes
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_responsive_image
|
||||||
|
config = Config.new(@site).to_h
|
||||||
|
use_cache = config['cache'] || @attributes['cache']
|
||||||
|
cache_key = @attributes.to_s
|
||||||
|
result = use_cache ? RenderCache.get(cache_key) : nil
|
||||||
|
|
||||||
|
if result.nil?
|
||||||
|
image = ImageProcessor.process(@attributes['path'], config)
|
||||||
|
@attributes['original'] = image[:original]
|
||||||
|
@attributes['resized'] = image[:resized]
|
||||||
|
|
||||||
|
@attributes['resized'].each { |resized| keep_resized_image!(@site, resized) }
|
||||||
|
|
||||||
|
image_template = @site.in_source_dir(@attributes['template'] || config['template'])
|
||||||
|
partial = File.read(image_template)
|
||||||
|
template = Liquid::Template.parse(partial)
|
||||||
|
|
||||||
|
info = {
|
||||||
|
registers: { site: @site }
|
||||||
|
}
|
||||||
|
|
||||||
|
result = template.render!(@attributes.merge(@site.site_payload), info)
|
||||||
|
|
||||||
|
RenderCache.set(cache_key, result)
|
||||||
|
end
|
||||||
|
|
||||||
|
result
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,111 @@
|
||||||
|
module Jekyll
|
||||||
|
module ResponsiveImage
|
||||||
|
class ResizeHandler
|
||||||
|
include ResponsiveImage::Utils
|
||||||
|
|
||||||
|
attr_reader :original_image
|
||||||
|
|
||||||
|
def initialize(original_image_absolute_path, config)
|
||||||
|
@config = config
|
||||||
|
|
||||||
|
@original_image_absolute_path = original_image_absolute_path
|
||||||
|
|
||||||
|
if @config['auto_rotate']
|
||||||
|
load_full_image
|
||||||
|
@original_image.auto_orient!
|
||||||
|
else
|
||||||
|
load_image_properties_only
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def resize_image
|
||||||
|
resized = []
|
||||||
|
|
||||||
|
@config['sizes'].each do |size|
|
||||||
|
width = size['width']
|
||||||
|
ratio = width.to_f / @original_image.columns.to_f
|
||||||
|
height = (@original_image.rows.to_f * ratio).round
|
||||||
|
|
||||||
|
next unless needs_resizing?(width)
|
||||||
|
|
||||||
|
image_path = @original_image.filename.force_encoding(Encoding::UTF_8)
|
||||||
|
filepath = format_output_path(@config['output_path_format'], @config, image_path, width, height)
|
||||||
|
resized.push(image_hash(@config, filepath, width, height))
|
||||||
|
|
||||||
|
site_source_filepath = File.expand_path(filepath, @config[:site_source])
|
||||||
|
site_dest_filepath = File.expand_path(filepath, @config[:site_dest])
|
||||||
|
|
||||||
|
if @config['save_to_source']
|
||||||
|
target_filepath = site_source_filepath
|
||||||
|
else
|
||||||
|
target_filepath = site_dest_filepath
|
||||||
|
end
|
||||||
|
|
||||||
|
# Don't resize images more than once
|
||||||
|
next if File.exist?(target_filepath)
|
||||||
|
|
||||||
|
ensure_output_dir_exists!(target_filepath)
|
||||||
|
ensure_output_dir_exists!(site_dest_filepath)
|
||||||
|
|
||||||
|
Jekyll.logger.info "Generating #{target_filepath}"
|
||||||
|
|
||||||
|
load_full_image unless @original_image_pixels_loaded
|
||||||
|
|
||||||
|
if @config['strip']
|
||||||
|
@original_image.strip!
|
||||||
|
end
|
||||||
|
|
||||||
|
i = @original_image.scale(ratio)
|
||||||
|
|
||||||
|
quality = size['quality'] || @config['default_quality']
|
||||||
|
|
||||||
|
i.write(target_filepath) do |f|
|
||||||
|
f.interlace = i.interlace
|
||||||
|
f.quality = quality
|
||||||
|
end
|
||||||
|
|
||||||
|
if @config['save_to_source']
|
||||||
|
# Ensure the generated file is copied to the _site directory
|
||||||
|
Jekyll.logger.info "Copying resized image to #{site_dest_filepath}"
|
||||||
|
FileUtils.copy_file(site_source_filepath, site_dest_filepath)
|
||||||
|
end
|
||||||
|
|
||||||
|
i.destroy!
|
||||||
|
end
|
||||||
|
|
||||||
|
@original_image.destroy!
|
||||||
|
|
||||||
|
resized
|
||||||
|
end
|
||||||
|
|
||||||
|
def format_output_path(format, config, image_path, width, height)
|
||||||
|
params = symbolize_keys(image_hash(config, image_path, width, height))
|
||||||
|
|
||||||
|
Pathname.new(format % params).cleanpath.to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def needs_resizing?(width)
|
||||||
|
@original_image.columns > width
|
||||||
|
end
|
||||||
|
|
||||||
|
def load_full_image
|
||||||
|
@original_image = Magick::Image::read(@original_image_absolute_path).first
|
||||||
|
@original_image_pixels_loaded = true
|
||||||
|
end
|
||||||
|
|
||||||
|
def load_image_properties_only
|
||||||
|
@original_image = Magick::Image::ping(@original_image_absolute_path).first
|
||||||
|
@original_image_pixels_loaded = false
|
||||||
|
end
|
||||||
|
|
||||||
|
def ensure_output_dir_exists!(path)
|
||||||
|
dir = File.dirname(path)
|
||||||
|
|
||||||
|
unless Dir.exist?(dir)
|
||||||
|
Jekyll.logger.info "Creating output directory #{dir}"
|
||||||
|
FileUtils.mkdir_p(dir)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -13,7 +13,7 @@ module Jekyll
|
||||||
end
|
end
|
||||||
|
|
||||||
def render(context)
|
def render(context)
|
||||||
Renderer.new(context.registers[:site], @attributes).render
|
Renderer.new(context.registers[:site], @attributes).render_responsive_image
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -16,17 +16,11 @@ module Jekyll
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
def format_output_path(format, base_path, image_path, width, height)
|
|
||||||
params = symbolize_keys(image_hash(base_path, image_path, width, height))
|
|
||||||
|
|
||||||
Pathname.new(format % params).cleanpath.to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
# Build a hash containing image information
|
# Build a hash containing image information
|
||||||
def image_hash(base_path, image_path, width, height)
|
def image_hash(config, image_path, width, height)
|
||||||
{
|
{
|
||||||
'path' => image_path,
|
'path' => image_path,
|
||||||
'dirname' => relative_dirname(base_path, image_path),
|
'dirname' => relative_dirname(config, image_path),
|
||||||
'basename' => File.basename(image_path),
|
'basename' => File.basename(image_path),
|
||||||
'filename' => File.basename(image_path, '.*'),
|
'filename' => File.basename(image_path, '.*'),
|
||||||
'extension' => File.extname(image_path).delete('.'),
|
'extension' => File.extname(image_path).delete('.'),
|
||||||
|
@ -35,9 +29,9 @@ module Jekyll
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def relative_dirname(base_path, image_path)
|
def relative_dirname(config, image_path)
|
||||||
path = Pathname.new(image_path).expand_path
|
path = Pathname.new(File.expand_path(image_path, config[:site_source]))
|
||||||
base = Pathname.new(base_path).expand_path
|
base = Pathname.new(File.expand_path(config['base_path'], config[:site_source]))
|
||||||
|
|
||||||
path.relative_path_from(base).dirname.to_s.delete('.')
|
path.relative_path_from(base).dirname.to_s.delete('.')
|
||||||
end
|
end
|
|
@ -1,5 +1,5 @@
|
||||||
module Jekyll
|
module Jekyll
|
||||||
module ResponsiveImage
|
module ResponsiveImage
|
||||||
VERSION = '1.0.0.pre3'.freeze
|
VERSION = '1.6.0'.freeze
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -1,19 +0,0 @@
|
||||||
require 'fileutils'
|
|
||||||
require 'yaml'
|
|
||||||
|
|
||||||
require 'jekyll'
|
|
||||||
require 'rmagick'
|
|
||||||
|
|
||||||
require 'jekyll/responsive_image/version'
|
|
||||||
require 'jekyll/responsive_image/config'
|
|
||||||
require 'jekyll/responsive_image/render_cache'
|
|
||||||
require 'jekyll/responsive_image/image'
|
|
||||||
require 'jekyll/responsive_image/image_processor'
|
|
||||||
require 'jekyll/responsive_image/image_resizer'
|
|
||||||
require 'jekyll/responsive_image/renderer'
|
|
||||||
require 'jekyll/responsive_image/tag'
|
|
||||||
require 'jekyll/responsive_image/block'
|
|
||||||
require 'jekyll/responsive_image/extra_image_generator'
|
|
||||||
|
|
||||||
Liquid::Template.register_tag('responsive_image', Jekyll::ResponsiveImage::Tag)
|
|
||||||
Liquid::Template.register_tag('responsive_image_block', Jekyll::ResponsiveImage::Block)
|
|
|
@ -1,10 +0,0 @@
|
||||||
module Jekyll
|
|
||||||
module ResponsiveImage
|
|
||||||
class Block < Liquid::Block
|
|
||||||
def render(context)
|
|
||||||
attributes = YAML.load(super)
|
|
||||||
Renderer.new(context.registers[:site], attributes).render
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,22 +0,0 @@
|
||||||
module Jekyll
|
|
||||||
module ResponsiveImage
|
|
||||||
class Config
|
|
||||||
DEFAULTS = {
|
|
||||||
'default_quality' => 85,
|
|
||||||
'base_path' => 'assets',
|
|
||||||
'output_path_format' => 'assets/resized/%{filename}-%{width}x%{height}.%{extension}',
|
|
||||||
'sizes' => [],
|
|
||||||
'extra_images' => []
|
|
||||||
}
|
|
||||||
|
|
||||||
def initialize(site)
|
|
||||||
@site = site
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_h
|
|
||||||
DEFAULTS.merge(@site.config['responsive_image'])
|
|
||||||
.merge(site_source: @site.source, site_dest: @site.dest)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,15 +0,0 @@
|
||||||
module Jekyll
|
|
||||||
module ResponsiveImage
|
|
||||||
@defaults = {
|
|
||||||
'default_quality' => 85,
|
|
||||||
'base_path' => 'assets',
|
|
||||||
'output_path_format' => 'assets/resized/%{filename}-%{width}x%{height}.%{extension}',
|
|
||||||
'sizes' => [],
|
|
||||||
'extra_images' => []
|
|
||||||
}.freeze
|
|
||||||
|
|
||||||
class << self
|
|
||||||
attr_reader :defaults
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,19 +0,0 @@
|
||||||
module Jekyll
|
|
||||||
module ResponsiveImage
|
|
||||||
class ExtraImageGenerator < Jekyll::Generator
|
|
||||||
def generate(site)
|
|
||||||
renderer = Renderer.new(site, {})
|
|
||||||
config = Config.new(site).to_h
|
|
||||||
|
|
||||||
config['extra_images'].each do |pathspec|
|
|
||||||
Dir.glob(site.in_source_dir(pathspec)) do |image_path|
|
|
||||||
relative_image_path = image_path.sub(/^#{Regexp.escape(image_path)}/, '')
|
|
||||||
|
|
||||||
result = ImageProcessor.process(image_path, relative_image_path, config)
|
|
||||||
result[:resized].each { |image| keep_resized_image!(site, image) }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,38 +0,0 @@
|
||||||
require 'pathname'
|
|
||||||
|
|
||||||
module Jekyll
|
|
||||||
module ResponsiveImage
|
|
||||||
class Image
|
|
||||||
def initialize(path, width, height, config)
|
|
||||||
@path = path.force_encoding(Encoding::UTF_8)
|
|
||||||
@width = width
|
|
||||||
@height = height
|
|
||||||
@config = config
|
|
||||||
end
|
|
||||||
|
|
||||||
# The directory name, relative to base_path
|
|
||||||
def dirname
|
|
||||||
base_path = Pathname.new(File.join(@config[:site_source], @config['base_path']))
|
|
||||||
image_path = Pathname.new(File.join(@config[:site_source], @path))
|
|
||||||
|
|
||||||
image_path.relative_path_from(base_path).dirname.to_s.delete('.')
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_h
|
|
||||||
{
|
|
||||||
'basename' => File.basename(@path),
|
|
||||||
'dirname' => dirname,
|
|
||||||
'extension' => File.extname(@path).delete('.'),
|
|
||||||
'filename' => File.basename(@path, '.*'),
|
|
||||||
'height' => @height,
|
|
||||||
'path' => @path,
|
|
||||||
'width' => @width
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_liquid
|
|
||||||
to_h
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,20 +0,0 @@
|
||||||
module Jekyll
|
|
||||||
module ResponsiveImage
|
|
||||||
class ImageProcessor
|
|
||||||
def self.process(path, config)
|
|
||||||
self.new.process(path, config)
|
|
||||||
end
|
|
||||||
|
|
||||||
def process(path, config)
|
|
||||||
raise SyntaxError.new("Invalid image path specified: #{path}") unless File.file?(path)
|
|
||||||
|
|
||||||
image = Magick::Image::read(path).first
|
|
||||||
|
|
||||||
{
|
|
||||||
original: Image.new(image.filename, image.columns, image.rows, config),
|
|
||||||
resized: ImageResizer.resize(image, config),
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,71 +0,0 @@
|
||||||
module Jekyll
|
|
||||||
module ResponsiveImage
|
|
||||||
class ImageResizer
|
|
||||||
def self.resize(image, config)
|
|
||||||
self.new.resize(image, config)
|
|
||||||
end
|
|
||||||
|
|
||||||
def resize(image, config)
|
|
||||||
results = []
|
|
||||||
|
|
||||||
config['sizes'].each do |size|
|
|
||||||
width = size['width']
|
|
||||||
ratio = width.to_f / image.columns.to_f
|
|
||||||
height = (image.rows.to_f * ratio).round
|
|
||||||
|
|
||||||
next unless needs_resizing?(image, width)
|
|
||||||
|
|
||||||
image_path = image.filename
|
|
||||||
source_img = Image.new(image_path, width, height, config)
|
|
||||||
site_source_path = format_output_path(config['output_path_format'], source_img.to_h)
|
|
||||||
|
|
||||||
resized_img = Image.new(site_source_path, width, height, config)
|
|
||||||
results.push(resized_img)
|
|
||||||
|
|
||||||
# Don't resize images more than once
|
|
||||||
next if File.exist?(site_source_path)
|
|
||||||
|
|
||||||
site_dest_path = File.join(config[:site_dest], site_source_path)
|
|
||||||
ensure_output_dir_exists!(site_source_path)
|
|
||||||
ensure_output_dir_exists!(site_dest_path)
|
|
||||||
|
|
||||||
Jekyll.logger.info "Generating #{site_source_path}"
|
|
||||||
|
|
||||||
resized = image.scale(ratio)
|
|
||||||
resized.write(site_source_path) do |i|
|
|
||||||
i.quality = size['quality'] || config['default_quality']
|
|
||||||
end
|
|
||||||
|
|
||||||
# Ensure the generated file is copied to the _site directory
|
|
||||||
Jekyll.logger.info "Copying image to #{site_dest_path}"
|
|
||||||
FileUtils.copy_file(site_source_path, site_dest_path)
|
|
||||||
end
|
|
||||||
|
|
||||||
results
|
|
||||||
end
|
|
||||||
|
|
||||||
def format_output_path(format, image_hash)
|
|
||||||
params = symbolize_keys(image_hash)
|
|
||||||
|
|
||||||
Pathname.new(format % params).cleanpath.to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
def symbolize_keys(hash)
|
|
||||||
hash.each_with_object({}){ |(key, val), h| h[key.to_sym] = val }
|
|
||||||
end
|
|
||||||
|
|
||||||
def needs_resizing?(image, width)
|
|
||||||
image.columns > width
|
|
||||||
end
|
|
||||||
|
|
||||||
def ensure_output_dir_exists!(path)
|
|
||||||
dir = File.dirname(path)
|
|
||||||
|
|
||||||
unless Dir.exist?(dir)
|
|
||||||
Jekyll.logger.info "Creating output directory #{dir}"
|
|
||||||
FileUtils.mkdir_p(dir)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,33 +0,0 @@
|
||||||
module Jekyll
|
|
||||||
module ResponsiveImage
|
|
||||||
class Renderer
|
|
||||||
attr_reader :site, :attributes
|
|
||||||
|
|
||||||
def initialize(site, attributes)
|
|
||||||
@site = site
|
|
||||||
@attributes = attributes
|
|
||||||
end
|
|
||||||
|
|
||||||
def render
|
|
||||||
cache_key = attributes.to_s
|
|
||||||
result = attributes['cache'] ? RenderCache.get(cache_key) : nil
|
|
||||||
|
|
||||||
if result.nil?
|
|
||||||
config = Config.new(site).to_h
|
|
||||||
|
|
||||||
image = ImageProcessor.process(attributes['path'], config)
|
|
||||||
template_vars = attributes.merge(site.site_payload)
|
|
||||||
.merge('original' => image[:original], 'resized' => image[:resized])
|
|
||||||
|
|
||||||
image_template = site.in_source_dir(attributes['template'] || config['template'])
|
|
||||||
template = Liquid::Template.parse(File.read(image_template))
|
|
||||||
result = template.render(template_vars)
|
|
||||||
|
|
||||||
RenderCache.set(cache_key, result)
|
|
||||||
end
|
|
||||||
|
|
||||||
result
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,57 +0,0 @@
|
||||||
module Jekyll
|
|
||||||
module 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)
|
|
||||||
|
|
||||||
image_path = img.filename.force_encoding(Encoding::UTF_8)
|
|
||||||
filepath = format_output_path(config['output_path_format'], config['base_path'], image_path, width, height)
|
|
||||||
resized.push(image_hash(config['base_path'], filepath, width, height))
|
|
||||||
|
|
||||||
site_source_filepath = File.expand_path(filepath, config[:site_source])
|
|
||||||
site_dest_filepath = File.expand_path(filepath, config[:site_dest])
|
|
||||||
|
|
||||||
# Don't resize images more than once
|
|
||||||
next if File.exist?(site_source_filepath)
|
|
||||||
|
|
||||||
ensure_output_dir_exists!(File.dirname(site_source_filepath))
|
|
||||||
ensure_output_dir_exists!(File.dirname(site_dest_filepath))
|
|
||||||
|
|
||||||
Jekyll.logger.info "Generating #{filepath}"
|
|
||||||
|
|
||||||
i = img.scale(ratio)
|
|
||||||
i.write(site_source_filepath) do |f|
|
|
||||||
f.quality = size['quality'] || config['default_quality']
|
|
||||||
end
|
|
||||||
|
|
||||||
# Ensure the generated file is copied to the _site directory
|
|
||||||
FileUtils.copy_file(site_source_filepath, site_dest_filepath)
|
|
||||||
|
|
||||||
i.destroy!
|
|
||||||
end
|
|
||||||
|
|
||||||
img.destroy!
|
|
||||||
|
|
||||||
resized
|
|
||||||
end
|
|
||||||
|
|
||||||
def needs_resizing?(img, width)
|
|
||||||
img.columns > width
|
|
||||||
end
|
|
||||||
|
|
||||||
def ensure_output_dir_exists!(dir)
|
|
||||||
unless Dir.exist?(dir)
|
|
||||||
Jekyll.logger.info "Creating output directory #{dir}"
|
|
||||||
FileUtils.mkdir_p(dir)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
{% comment %}
|
||||||
|
Render your responsive images using Imager.js (https://github.com/BBC-News/Imager.js/), with the smallest resized image used as a fallback.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
{% responsive_image path: assets/image.jpg alt: "A description of the image" %}
|
||||||
|
|
||||||
|
(P.S. You can safely delete this comment block)
|
||||||
|
{% endcomment %}
|
||||||
|
|
||||||
|
{% assign smallest = resized | sort: 'width' | first %}
|
||||||
|
|
||||||
|
<div class="responsive-image">
|
||||||
|
<img class="responsive-image__placeholder" src="/{{ smallest.path }}">
|
||||||
|
<div class="responsive-image__delayed" data-src="/assets/resized/{width}/{{ original.basename }}"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
new Imager('.responsive-image__delayed', {
|
||||||
|
availableWidths: [{{ resized | map: 'width' | join: ', ' }}],
|
||||||
|
onImagesReplaced: function() {
|
||||||
|
$('.responsive-image__placeholder').hide()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
|
@ -0,0 +1,16 @@
|
||||||
|
{% comment %}
|
||||||
|
Render your responsive images using <picture>, with the original asset used as a fallback. Note: If your original assets are not web-friendly (e.g. they are very large), you can use a resized image as the fallback instead. See the srcset-resized-fallback.html template for how to do this.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
{% responsive_image path: assets/image.jpg alt: "A description of the image" %}
|
||||||
|
|
||||||
|
(P.S. You can safely delete this comment block)
|
||||||
|
{% endcomment %}
|
||||||
|
|
||||||
|
<picture>
|
||||||
|
{% for i in resized %}
|
||||||
|
<source media="(min-width: {{ i.width }}px)" srcset="/{{ i.path }}">
|
||||||
|
{% endfor %}
|
||||||
|
<img src="/{{ path }}">
|
||||||
|
</picture>
|
|
@ -0,0 +1,18 @@
|
||||||
|
{% comment %}
|
||||||
|
Render your responsive images using <img srcset>, with the largest resized image used as a fallback.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
{% responsive_image path: assets/image.jpg alt: "A description of the image" %}
|
||||||
|
|
||||||
|
(P.S. You can safely delete this comment block)
|
||||||
|
{% endcomment %}
|
||||||
|
|
||||||
|
{% assign largest = resized | sort: 'width' | last %}
|
||||||
|
{% capture srcset %}
|
||||||
|
{% for i in resized %}
|
||||||
|
/{{ i.path }} {{ i.width }}w,
|
||||||
|
{% endfor %}
|
||||||
|
{% endcapture %}
|
||||||
|
|
||||||
|
<img src="/{{ largest.path }}" alt="{{ alt }}" srcset="{{ srcset | strip_newlines }} /{{ path }} {{ original.width }}w">
|
|
@ -0,0 +1,17 @@
|
||||||
|
{% comment %}
|
||||||
|
Render your responsive images using <img srcset>, with the original asset used as a fallback. Note: If your original assets are not web-friendly (e.g. they are very large), you might prefer to use the srcset-resized-fallback.html template.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
{% responsive_image path: assets/image.jpg alt: "A description of the image" %}
|
||||||
|
|
||||||
|
(P.S. You can safely delete this comment block)
|
||||||
|
{% endcomment %}
|
||||||
|
|
||||||
|
{% capture srcset %}
|
||||||
|
{% for i in resized %}
|
||||||
|
/{{ i.path }} {{ i.width }}w,
|
||||||
|
{% endfor %}
|
||||||
|
{% endcapture %}
|
||||||
|
|
||||||
|
<img src="/{{ path }}" alt="{{ alt }}" srcset="{{ srcset | strip_newlines }} /{{ path }} {{ original.width }}w">
|
Loading…
Reference in New Issue