middleman-imageoptim 0.1.4 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +5 -0
- data/.rubocop_todo.yml +46 -0
- data/.simplecov +7 -0
- data/.travis.yml +1 -2
- data/Gemfile +1 -11
- data/README.md +35 -19
- data/Rakefile +11 -19
- data/features/manifest.feature +31 -0
- data/features/optimization.feature +10 -0
- data/features/permissions.feature +14 -0
- data/features/support/env.rb +7 -0
- data/features/support/step_definitions.rb +39 -0
- data/fixtures/basic-app/config-disabled-manifest.rb +3 -0
- data/fixtures/basic-app/config.rb +1 -0
- data/fixtures/basic-app/source/images/oh_my_glob.gif +0 -0
- data/fixtures/basic-app/source/images/table.jpg +0 -0
- data/lib/middleman-imageoptim.rb +12 -8
- data/lib/middleman-imageoptim/extension.rb +14 -13
- data/lib/middleman-imageoptim/manifest.rb +52 -0
- data/lib/middleman-imageoptim/manifest_resource.rb +41 -0
- data/lib/middleman-imageoptim/optimizer.rb +71 -74
- data/lib/middleman-imageoptim/options.rb +46 -56
- data/lib/middleman-imageoptim/resource_list.rb +72 -0
- data/lib/middleman-imageoptim/utils.rb +42 -0
- data/lib/middleman-imageoptim/version.rb +1 -1
- data/lib/middleman_extension.rb +1 -1
- data/middleman-imageoptim.gemspec +19 -16
- data/script/spec +20 -5
- data/spec/spec_helper.rb +4 -7
- data/spec/unit/options_spec.rb +97 -48
- data/spec/unit/utils_spec.rb +55 -0
- metadata +70 -16
- data/.cane +0 -4
- data/spec/unit/optimizer_spec.rb +0 -58
- data/spec/use_coveralls.rb +0 -2
- data/spec/use_simplecov.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 139f5d4341e9f282b48469c083333f52954d41c2
|
4
|
+
data.tar.gz: c43cb5965b95b8628f66e5f7472b7cee64cfe26f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 84a90a10b3d1867a69b8a99adfd43e407bd80950e52f56e75b03b30fd9add3e9b14ff17a4a85cfcbbf6f6d67530650fbcc5a6de01f7951cb5cdfb3c33ad01fb3
|
7
|
+
data.tar.gz: 6cf1a88f097cb595b7db35204fabaa6c21532550132720d63adbed7b53bb5688435c211d3beee32f5a7e3742e1824b8fb1437e2b7ff8af3a15a7f7e2f6ad0af4
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# This configuration was generated by `rubocop --auto-gen-config`
|
2
|
+
# on 2015-01-05 15:23:36 +1100 using RuboCop version 0.27.1.
|
3
|
+
# The point is for the user to remove these configuration records
|
4
|
+
# one by one as the offenses are removed from the code base.
|
5
|
+
# Note that changes in the inspected code, or installation of new
|
6
|
+
# versions of RuboCop, may require this file to be generated again.
|
7
|
+
|
8
|
+
# Offense count: 1
|
9
|
+
Lint/AmbiguousOperator:
|
10
|
+
Enabled: false
|
11
|
+
|
12
|
+
# Offense count: 1
|
13
|
+
Lint/AmbiguousRegexpLiteral:
|
14
|
+
Enabled: false
|
15
|
+
|
16
|
+
# Offense count: 11
|
17
|
+
# Configuration parameters: AllowURI, URISchemes.
|
18
|
+
Metrics/LineLength:
|
19
|
+
Max: 133
|
20
|
+
|
21
|
+
# Offense count: 1
|
22
|
+
# Configuration parameters: CountComments.
|
23
|
+
Metrics/MethodLength:
|
24
|
+
Max: 11
|
25
|
+
|
26
|
+
# Offense count: 1
|
27
|
+
Style/AccessorMethodName:
|
28
|
+
Enabled: false
|
29
|
+
|
30
|
+
# Offense count: 7
|
31
|
+
Style/Documentation:
|
32
|
+
Enabled: false
|
33
|
+
|
34
|
+
# Offense count: 1
|
35
|
+
Style/EachWithObject:
|
36
|
+
Enabled: false
|
37
|
+
|
38
|
+
# Offense count: 1
|
39
|
+
# Configuration parameters: Exclude.
|
40
|
+
Style/FileName:
|
41
|
+
Enabled: false
|
42
|
+
|
43
|
+
# Offense count: 1
|
44
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
45
|
+
Style/FormatString:
|
46
|
+
Enabled: false
|
data/.simplecov
ADDED
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -1,12 +1,2 @@
|
|
1
|
-
|
2
|
-
# the following line to use "https"
|
3
|
-
source 'http://rubygems.org'
|
4
|
-
|
5
|
-
# Specify your gem's dependencies in middleman-imageoptim.gemspec
|
1
|
+
source 'https://rubygems.org'
|
6
2
|
gemspec
|
7
|
-
|
8
|
-
group :development do
|
9
|
-
gem "rake", "~> 0.9.2"
|
10
|
-
gem "rdoc", "~> 3.9"
|
11
|
-
gem "yard", "~> 0.8.0"
|
12
|
-
end
|
data/README.md
CHANGED
@@ -5,10 +5,12 @@
|
|
5
5
|
Serving big images is for numb-skulls! Compress and optimise your imagery during `middleman build` by running [image_optim](https://github.com/toy/image_optim) over it. Aww yiss!
|
6
6
|
|
7
7
|
[![Build Status](https://travis-ci.org/plasticine/middleman-imageoptim.png?branch=master)](https://travis-ci.org/plasticine/middleman-imageoptim)
|
8
|
-
[![
|
8
|
+
[![Code Climate](https://codeclimate.com/github/plasticine/middleman-imageoptim.png)](https://codeclimate.com/github/plasticine/middleman-imageoptim)
|
9
9
|
[![Gem Version](https://badge.fury.io/rb/middleman-imageoptim.png)](http://badge.fury.io/rb/middleman-imageoptim)
|
10
10
|
[![Dependency Status](https://gemnasium.com/plasticine/middleman-imageoptim.png)](https://gemnasium.com/plasticine/middleman-imageoptim)
|
11
11
|
|
12
|
+
* * *
|
13
|
+
|
12
14
|
![](http://cl.ly/image/0h0b330F2p3C/Terminal%20%E2%80%94%20zsh%20%E2%80%94%20109%C3%9712.png)
|
13
15
|
|
14
16
|
## Installation
|
@@ -16,7 +18,7 @@ Serving big images is for numb-skulls! Compress and optimise your imagery during
|
|
16
18
|
Go set up the [image_optim](https://github.com/toy/image_optim) external utilities, then;
|
17
19
|
|
18
20
|
```ruby
|
19
|
-
gem
|
21
|
+
gem 'middleman-imageoptim'
|
20
22
|
```
|
21
23
|
|
22
24
|
## Usage
|
@@ -30,7 +32,13 @@ Below is the default configuration showing all available options;
|
|
30
32
|
|
31
33
|
```ruby
|
32
34
|
activate :imageoptim do |options|
|
33
|
-
#
|
35
|
+
# Use a build manifest to prevent re-compressing images between builds
|
36
|
+
options.manifest = true
|
37
|
+
|
38
|
+
# Silence problematic image_optim workers
|
39
|
+
options.skip_missing_workers = true
|
40
|
+
|
41
|
+
# Cause image_optim to be in shouty-mode
|
34
42
|
options.verbose = false
|
35
43
|
|
36
44
|
# Setting these to true or nil will let options determine them (recommended)
|
@@ -38,17 +46,18 @@ activate :imageoptim do |options|
|
|
38
46
|
options.threads = true
|
39
47
|
|
40
48
|
# Image extensions to attempt to compress
|
41
|
-
options.image_extensions = %w(.png .jpg .gif)
|
49
|
+
options.image_extensions = %w(.png .jpg .gif .svg)
|
42
50
|
|
43
|
-
#
|
51
|
+
# Compressor worker options, individual optimisers can be disabled by passing
|
44
52
|
# false instead of a hash
|
45
|
-
options.
|
46
|
-
options.
|
47
|
-
options.
|
48
|
-
options.
|
49
|
-
options.
|
50
|
-
options.
|
51
|
-
options.
|
53
|
+
options.advpng = { :level => 4 }
|
54
|
+
options.gifsicle = { :interlace => false }
|
55
|
+
options.jpegoptim = { :strip => ['all'], :max_quality => 100 }
|
56
|
+
options.jpegtran = { :copy_chunks => false, :progressive => true, :jpegrescan => true }
|
57
|
+
options.optipng = { :level => 6, :interlace => false }
|
58
|
+
options.pngcrush = { :chunks => ['alla'], :fix => false, :brute => false }
|
59
|
+
options.pngout = { :copy_chunks => false, :strategy => 0 }
|
60
|
+
options.svgo = {}
|
52
61
|
end
|
53
62
|
```
|
54
63
|
|
@@ -56,19 +65,26 @@ end
|
|
56
65
|
|
57
66
|
## Changelog
|
58
67
|
|
68
|
+
##### `0.2.0`
|
69
|
+
- Big cleanup to codebase.
|
70
|
+
- More tests.
|
71
|
+
- Caching between builds using a manifest file to skip over already-compressed assets (thanks for your work on this @jagthedrummer).
|
72
|
+
- Updates `image_optim` gem to latest version (`0.20.2`).
|
73
|
+
- Adds dependency on `image_optim_pack` to ensure that binaries are available.
|
74
|
+
|
59
75
|
##### `0.1.4`
|
60
|
-
- Respect plugin ordering in config.rb (thanks @jeffutter) [#8](https://github.com/plasticine/middleman-imageoptim/pull/8)
|
76
|
+
- Respect plugin ordering in config.rb (thanks @jeffutter) [#8](https://github.com/plasticine/middleman-imageoptim/pull/8).
|
61
77
|
|
62
78
|
##### `0.1.3`
|
63
|
-
-
|
79
|
+
- Fix missing license in gemspec.
|
64
80
|
|
65
81
|
##### `0.1.2`
|
66
|
-
-
|
82
|
+
- Minor bugfix.
|
67
83
|
|
68
84
|
##### `0.1.1`
|
69
|
-
-
|
85
|
+
- Remove legacy requirement for padrino.
|
70
86
|
|
71
87
|
##### `0.1.0`
|
72
|
-
-
|
73
|
-
-
|
74
|
-
-
|
88
|
+
- Complete refactor and clean-up.
|
89
|
+
- Introduced an options class. options now work (lol, yay!), thanks @andrew-aladev for your help there.
|
90
|
+
- Change of extension activation name from `:image_optim` to `:imageoptim` for consistency with internal naming.
|
data/Rakefile
CHANGED
@@ -5,29 +5,21 @@ Bundler::GemHelper.install_tasks
|
|
5
5
|
|
6
6
|
require 'rake/clean'
|
7
7
|
require 'rspec/core/rake_task'
|
8
|
+
require 'cucumber'
|
9
|
+
require 'cucumber/rake/task'
|
8
10
|
|
9
11
|
namespace :spec do
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
cane.abc_max = 10
|
15
|
-
cane.add_threshold 'coverage/covered_percent', :>=, 74
|
16
|
-
cane.no_style = true
|
17
|
-
cane.abc_exclude = %w(Middleman::Imageoptim::Optimizer#optimizer)
|
18
|
-
end
|
19
|
-
|
20
|
-
task :default => :quality
|
21
|
-
rescue LoadError
|
22
|
-
warn "cane not available, quality task not provided."
|
12
|
+
desc 'Run unit specs'
|
13
|
+
RSpec::Core::RakeTask.new(:unit) do |config|
|
14
|
+
config.pattern = 'spec/unit/*_spec.rb'
|
15
|
+
config.rspec_opts = '--require spec_helper'
|
23
16
|
end
|
24
17
|
|
25
|
-
desc 'Run
|
26
|
-
|
27
|
-
|
28
|
-
spec.rspec_opts = "--require spec_helper"
|
18
|
+
desc 'Run feature tests'
|
19
|
+
Cucumber::Rake::Task.new(:features) do |config|
|
20
|
+
config.cucumber_opts = 'features --format pretty'
|
29
21
|
end
|
30
22
|
end
|
31
23
|
|
32
|
-
desc 'Default: run
|
33
|
-
task :
|
24
|
+
desc 'Default: run the tests.'
|
25
|
+
task default: ['spec:unit', 'spec:features']
|
@@ -0,0 +1,31 @@
|
|
1
|
+
Feature: Manifest
|
2
|
+
Scenario: Don't reoptimize images that have already been optimized
|
3
|
+
Given a fixture app "basic-app"
|
4
|
+
Given a successfully built app at "basic-app" with flags "--verbose"
|
5
|
+
Then the following files should exist:
|
6
|
+
| build/imageoptim.manifest.yml |
|
7
|
+
Then the manifest should have the right timestamp for "build/images/table.jpg"
|
8
|
+
|
9
|
+
Scenario: Don't write a manifest file if it is disabled
|
10
|
+
Given a fixture app "basic-app"
|
11
|
+
And app "basic-app" is using config "disabled-manifest"
|
12
|
+
Given a successfully built app at "basic-app" with flags "--verbose"
|
13
|
+
Then the following files should not exist:
|
14
|
+
| build/imageoptim.manifest.yml |
|
15
|
+
|
16
|
+
Scenario: Skipping optimization when the timestamp hasn't changed
|
17
|
+
Given a fixture app "basic-app"
|
18
|
+
Given a successfully built app at "basic-app" with flags "--verbose"
|
19
|
+
Given a modification time for a file named "build/images/table.jpg"
|
20
|
+
Given some time has passed
|
21
|
+
Given a successfully built app at "basic-app" with flags "--verbose"
|
22
|
+
Then the file "build/images/table.jpg" should not have been updated
|
23
|
+
|
24
|
+
Scenario: Regenerating the build image if the source has changed
|
25
|
+
Given a fixture app "basic-app"
|
26
|
+
Given a successfully built app at "basic-app" with flags "--verbose"
|
27
|
+
Given a modification time for a file named "build/images/table.jpg"
|
28
|
+
Given some time has passed
|
29
|
+
Given an updated file at "source/images/table.jpg"
|
30
|
+
Given a successfully built app at "basic-app" with flags "--verbose"
|
31
|
+
Then the file "build/images/table.jpg" should have been updated
|
@@ -0,0 +1,10 @@
|
|
1
|
+
Feature: Optimization
|
2
|
+
Scenario: Basic optimization
|
3
|
+
Given a fixture app "basic-app"
|
4
|
+
Then the following files should exist:
|
5
|
+
| source/images/table.jpg |
|
6
|
+
Then the file "source/images/table.jpg" should be 225252 bytes
|
7
|
+
Given a successfully built app at "basic-app" with flags "--verbose"
|
8
|
+
Then the following files should exist:
|
9
|
+
| build/images/table.jpg |
|
10
|
+
Then the file "build/images/table.jpg" should be less than 225252 bytes
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Feature: Permissions
|
2
|
+
Scenario: Preserving permissions
|
3
|
+
Given a fixture app "basic-app"
|
4
|
+
Then the following files should exist:
|
5
|
+
| source/images/table.jpg |
|
6
|
+
| source/images/oh_my_glob.gif |
|
7
|
+
Then the mode of filesystem object "source/images/table.jpg" should match "0644"
|
8
|
+
Then the mode of filesystem object "source/images/oh_my_glob.gif" should match "0644"
|
9
|
+
Given a successfully built app at "basic-app" with flags "--verbose"
|
10
|
+
Then the following files should exist:
|
11
|
+
| build/images/table.jpg |
|
12
|
+
| build/images/oh_my_glob.gif |
|
13
|
+
Then the mode of filesystem object "build/images/table.jpg" should match "0644"
|
14
|
+
Then the mode of filesystem object "build/images/oh_my_glob.gif" should match "0644"
|
@@ -0,0 +1,39 @@
|
|
1
|
+
Then(/^the file "(.*?)" should be (\d+) bytes$/) do |img, size|
|
2
|
+
expect(File.size(File.join(current_dir, img))).to eql(size.to_i)
|
3
|
+
end
|
4
|
+
|
5
|
+
Then(/^the file "(.*?)" should be less than (\d+) bytes$/) do |img, size|
|
6
|
+
expect(File.size(File.join(current_dir, img))).to be < size.to_i
|
7
|
+
end
|
8
|
+
|
9
|
+
Then(/^the manifest should have the right timestamp for "(.*?)"$/) do |file|
|
10
|
+
manifest = YAML.load(File.read(manifest_path))
|
11
|
+
file_stamp = File.mtime(File.join(current_dir, file))
|
12
|
+
expect(manifest[file]).to eql(file_stamp)
|
13
|
+
end
|
14
|
+
|
15
|
+
Given(/^a primed manifest for "(.*?)"$/) do |file|
|
16
|
+
manifest = { file: File.mtime(File.join(current_dir, file)) }
|
17
|
+
File.open(path, 'w') do |manifest_file|
|
18
|
+
manifest_file.write(YAML.dump(manifest))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
Given(/^some time has passed$/) do
|
23
|
+
# this needs to be > 1 to get out of the single second resolution of a
|
24
|
+
# file timestamp
|
25
|
+
sleep(1.5)
|
26
|
+
end
|
27
|
+
|
28
|
+
Given(/^an updated file at "(.*?)"$/) do |file|
|
29
|
+
FileUtils.touch(File.join(current_dir, file))
|
30
|
+
end
|
31
|
+
|
32
|
+
Then(/^the file "([^\"]*)" should have been updated$/) do |file|
|
33
|
+
target = File.join(current_dir, file)
|
34
|
+
expect(File.mtime(target)).not_to eql(@modification_times[target])
|
35
|
+
end
|
36
|
+
|
37
|
+
def manifest_path
|
38
|
+
File.join(current_dir, 'build', 'imageoptim.manifest.yml')
|
39
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
activate :imageoptim
|
Binary file
|
Binary file
|
data/lib/middleman-imageoptim.rb
CHANGED
@@ -1,15 +1,19 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require 'middleman-core'
|
2
|
+
require 'middleman-imageoptim/optimizer'
|
3
|
+
require 'middleman-imageoptim/options'
|
4
|
+
require 'middleman-imageoptim/resource_list'
|
5
|
+
require 'middleman-imageoptim/utils'
|
6
|
+
require 'middleman-imageoptim/manifest'
|
7
|
+
require 'middleman-imageoptim/manifest_resource'
|
4
8
|
|
5
9
|
::Middleman::Extensions.register(:imageoptim) do
|
6
|
-
require
|
7
|
-
::Middleman::Imageoptim
|
10
|
+
require 'middleman-imageoptim/extension'
|
11
|
+
::Middleman::Imageoptim::Extension
|
8
12
|
end
|
9
13
|
|
10
14
|
::Middleman::Extensions.register(:image_optim) do
|
11
|
-
warn
|
15
|
+
warn ':image_optim is deprecated. Please use `:imageoptim` instead.'
|
12
16
|
|
13
|
-
require
|
14
|
-
::Middleman::Imageoptim
|
17
|
+
require 'middleman-imageoptim/extension'
|
18
|
+
::Middleman::Imageoptim::Extension
|
15
19
|
end
|
@@ -1,24 +1,25 @@
|
|
1
|
-
require
|
1
|
+
require 'middleman-core'
|
2
2
|
|
3
3
|
module Middleman
|
4
|
-
|
5
4
|
# Middleman extension entry point
|
6
5
|
module Imageoptim
|
7
|
-
class
|
8
|
-
def
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
app.after_configuration do
|
6
|
+
class Extension < Middleman::Extension
|
7
|
+
def after_build(builder)
|
8
|
+
Middleman::Imageoptim::Optimizer.optimize!(app, builder, options)
|
9
|
+
end
|
13
10
|
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
def manipulate_resource_list(resources)
|
12
|
+
return resources unless options.manifest
|
13
|
+
Middleman::Imageoptim::ResourceList.manipulate(app, resources, options)
|
14
|
+
end
|
17
15
|
|
18
|
-
|
16
|
+
private
|
19
17
|
|
18
|
+
def setup_options(options_hash = {}, &_block)
|
19
|
+
@options = Middleman::Imageoptim::Options.new(options_hash)
|
20
|
+
yield @options if block_given?
|
21
|
+
@options.freeze
|
20
22
|
end
|
21
|
-
alias :included :registered
|
22
23
|
end
|
23
24
|
end
|
24
25
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Middleman
|
2
|
+
module Imageoptim
|
3
|
+
class Manifest
|
4
|
+
MANIFEST_FILENAME = 'imageoptim.manifest.yml'
|
5
|
+
|
6
|
+
attr_reader :app
|
7
|
+
|
8
|
+
def initialize(app)
|
9
|
+
@app = app
|
10
|
+
end
|
11
|
+
|
12
|
+
def path
|
13
|
+
File.join(app.build_dir, MANIFEST_FILENAME)
|
14
|
+
end
|
15
|
+
|
16
|
+
def build_and_write(new_resources)
|
17
|
+
write(dump(build(new_resources)))
|
18
|
+
end
|
19
|
+
|
20
|
+
def resource(key)
|
21
|
+
resources[key.to_s]
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def resources
|
27
|
+
@resources ||= load(path)
|
28
|
+
end
|
29
|
+
|
30
|
+
def dump(source)
|
31
|
+
YAML.dump(source)
|
32
|
+
end
|
33
|
+
|
34
|
+
def load(path)
|
35
|
+
YAML.load(File.read(path))
|
36
|
+
end
|
37
|
+
|
38
|
+
def build(resources)
|
39
|
+
resources.inject({}) do |new_manifest, resource|
|
40
|
+
new_manifest[resource.to_s] = File.mtime(resource)
|
41
|
+
new_manifest
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def write(manifest)
|
46
|
+
File.open(path, 'w') do |manifest_file|
|
47
|
+
manifest_file.write(manifest)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|