middleman-imageoptim 0.1.4 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +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
|
[](https://travis-ci.org/plasticine/middleman-imageoptim)
|
8
|
-
[](https://codeclimate.com/github/plasticine/middleman-imageoptim)
|
9
9
|
[](http://badge.fury.io/rb/middleman-imageoptim)
|
10
10
|
[](https://gemnasium.com/plasticine/middleman-imageoptim)
|
11
11
|
|
12
|
+
* * *
|
13
|
+
|
12
14
|

|
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
|