middleman-automatic-clowncar 0.0.1
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 +7 -0
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +47 -0
- data/Rakefile +1 -0
- data/features/clowncar_tag_build.feature +74 -0
- data/features/clowncar_tag_preview.feature +55 -0
- data/features/support/env.rb +7 -0
- data/features/thumbnail_generation.feature +22 -0
- data/fixtures/automatic-clowncar-app/config.rb +8 -0
- data/fixtures/automatic-clowncar-app/source/images/photos/test-image.jpg +0 -0
- data/fixtures/automatic-clowncar-app/source/index.html +0 -0
- data/fixtures/automatic-clowncar-app/source/tag.html.erb +1 -0
- data/lib/middleman-automatic-clowncar.rb +14 -0
- data/lib/middleman-automatic-clowncar/extension.rb +317 -0
- data/lib/middleman-automatic-clowncar/thumbnail-generator.rb +51 -0
- data/lib/middleman-automatic-clowncar/thumbnailer-extension.rb +27 -0
- data/lib/middleman-automatic-clowncar/version.rb +3 -0
- data/lib/middleman_extension.rb +1 -0
- data/middleman-automatic-clowncar.gemspec +29 -0
- metadata +166 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e3f381609ce148c96ba3b48ba277dc31268aeeae
|
4
|
+
data.tar.gz: 72947b12524e0dcb48f0c17daecab9f825915732
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8fcb75b7b390aaa2f4dfc761ec976d35ebcc9e25615b1cb234c907be6b878ef1256908d255bafd5a389a6ee7630b9564f33b3ecbb41354182ab72eea9897e8f2
|
7
|
+
data.tar.gz: 5810f5b54b7c7edf1e9401907b022b1f2b4cf12b662eeba42dddd5f73efed0741cb568b3393ee1deb89460576a21c1305d54a4d544f157e88ff31546e66f76a7
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Jeremy Green
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# Middleman::Automatic::Clowncar
|
2
|
+
|
3
|
+
Automatically generated responsive images for Middleman.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'middleman-automatic-clowncar'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install middleman-automatic-clowncar
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Activate the module in `config.rb` and pass in config options.
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
activate :automatic_clowncar,
|
25
|
+
:sizes => {
|
26
|
+
:small => 200,
|
27
|
+
:medium => 400,
|
28
|
+
:large => 600
|
29
|
+
},
|
30
|
+
:namespace_directory => %w(photos)
|
31
|
+
```
|
32
|
+
|
33
|
+
Then in a template you can use the `automatic_clowncar_tag` to display a
|
34
|
+
responsive image.
|
35
|
+
|
36
|
+
```erb
|
37
|
+
<%= automatic_clowncar_tag 'photos/my-photo.jpg' %>
|
38
|
+
```
|
39
|
+
|
40
|
+
|
41
|
+
## Contributing
|
42
|
+
|
43
|
+
1. Fork it ( http://github.com/<my-github-username>/middleman-automatic-clowncar/fork )
|
44
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
45
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
46
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
47
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,74 @@
|
|
1
|
+
Feature: Generating SVG clowncars during preview mode
|
2
|
+
|
3
|
+
Scenario: Basic command
|
4
|
+
Given a fixture app "automatic-clowncar-app"
|
5
|
+
And a file named "source/index.html.erb" with:
|
6
|
+
"""
|
7
|
+
<%= automatic_clowncar_tag "photos/test-image.jpg", :host => "http://localhost:4567/" %>
|
8
|
+
"""
|
9
|
+
Given a successfully built app at "automatic-clowncar-app" with flags "--verbose"
|
10
|
+
When I cd to "build"
|
11
|
+
#Then the following files should not exist:
|
12
|
+
# | images/photos/test-image.jpg |
|
13
|
+
Then the following files should exist:
|
14
|
+
| images/photos/test-image/test-image-small.jpg |
|
15
|
+
| images/photos/test-image/test-image-medium.jpg |
|
16
|
+
| images/photos/test-image/test-image-large.jpg |
|
17
|
+
Then the file "index.html" should contain "<object"
|
18
|
+
And the file "index.html" should contain "@media%20screen%20and%20(max-width:200px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/photos/test-image/test-image-small.jpg);%7D%7D"
|
19
|
+
And the file "index.html" should contain "@media%20screen%20and%20(min-width:201px)%20and%20(max-width:400px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/photos/test-image/test-image-medium.jpg);%7D%7D"
|
20
|
+
And the file "index.html" should contain "@media%20screen%20and%20(min-width:401px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/photos/test-image/test-image-large.jpg);%7D%7D"
|
21
|
+
|
22
|
+
Scenario: Basic command with asset_host
|
23
|
+
Given a fixture app "automatic-clowncar-app"
|
24
|
+
And a file named "config.rb" with:
|
25
|
+
"""
|
26
|
+
activate :automatic_clowncar,
|
27
|
+
:sizes => {
|
28
|
+
:small => 200,
|
29
|
+
:medium => 400,
|
30
|
+
:large => 600
|
31
|
+
},
|
32
|
+
:namespace_directory => %w(photos)
|
33
|
+
activate :asset_host, :host => "http://localhost:4567/"
|
34
|
+
"""
|
35
|
+
And a file named "source/index.html.erb" with:
|
36
|
+
"""
|
37
|
+
<%= automatic_clowncar_tag "photos/test-image.jpg" %>
|
38
|
+
"""
|
39
|
+
Given a successfully built app at "automatic-clowncar-app" with flags "--verbose"
|
40
|
+
When I cd to "build"
|
41
|
+
#Then the following files should not exist:
|
42
|
+
# | images/photos/test-image.jpg
|
43
|
+
Then the following files should exist:
|
44
|
+
| images/photos/test-image/test-image-small.jpg |
|
45
|
+
| images/photos/test-image/test-image-medium.jpg |
|
46
|
+
| images/photos/test-image/test-image-large.jpg |
|
47
|
+
Then the file "index.html" should contain "<object"
|
48
|
+
And the file "index.html" should contain "@media%20screen%20and%20(max-width:200px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/photos/test-image/test-image-small.jpg);%7D%7D"
|
49
|
+
And the file "index.html" should contain "@media%20screen%20and%20(min-width:201px)%20and%20(max-width:400px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/photos/test-image/test-image-medium.jpg);%7D%7D"
|
50
|
+
And the file "index.html" should contain "@media%20screen%20and%20(min-width:401px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/photos/test-image/test-image-large.jpg);%7D%7D"
|
51
|
+
|
52
|
+
Scenario: With OldIE Fallback
|
53
|
+
Given a fixture app "automatic-clowncar-app"
|
54
|
+
And a file named "source/index.html.erb" with:
|
55
|
+
"""
|
56
|
+
<%= automatic_clowncar_tag "photos/test-image.jpg", :host => "http://localhost:4567/", :fallback => true %>
|
57
|
+
"""
|
58
|
+
Given a successfully built app at "automatic-clowncar-app" with flags "--verbose"
|
59
|
+
When I cd to "build"
|
60
|
+
#Then the following files should not exist:
|
61
|
+
# | images/photos/test-image.jpg
|
62
|
+
Then the following files should exist:
|
63
|
+
| images/photos/test-image/test-image-small.jpg |
|
64
|
+
| images/photos/test-image/test-image-medium.jpg |
|
65
|
+
| images/photos/test-image/test-image-large.jpg |
|
66
|
+
Then the file "index.html" should contain "<object"
|
67
|
+
And the file "index.html" should contain "@media%20screen%20and%20(max-width:200px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/photos/test-image/test-image-small.jpg);%7D%7D"
|
68
|
+
And the file "index.html" should contain "@media%20screen%20and%20(min-width:201px)%20and%20(max-width:400px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/photos/test-image/test-image-medium.jpg);%7D%7D"
|
69
|
+
And the file "index.html" should contain "@media%20screen%20and%20(min-width:401px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/photos/test-image/test-image-large.jpg);%7D%7D"
|
70
|
+
And the file "index.html" should contain "<!--[if lte IE 8]>"
|
71
|
+
And the file "index.html" should contain '<img src="/images/photos/test-image/test-image-small.jpg">'
|
72
|
+
And the file "index.html" should contain "<![endif]-->"
|
73
|
+
|
74
|
+
|
@@ -0,0 +1,55 @@
|
|
1
|
+
Feature: Generating SVG clowncars during preview mode
|
2
|
+
|
3
|
+
Scenario: Basic command
|
4
|
+
Given a fixture app "automatic-clowncar-app"
|
5
|
+
And a file named "source/index.html.erb" with:
|
6
|
+
"""
|
7
|
+
<%= automatic_clowncar_tag "photos/test-image.jpg", :host => "http://localhost:4567/" %>
|
8
|
+
"""
|
9
|
+
And the Server is running at "automatic-clowncar-app"
|
10
|
+
When I go to "/index.html"
|
11
|
+
Then I should see "<object"
|
12
|
+
And I should see "@media%20screen%20and%20(max-width:200px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/photos/test-image/test-image-small.jpg);%7D%7D"
|
13
|
+
And I should see "@media%20screen%20and%20(min-width:201px)%20and%20(max-width:400px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/photos/test-image/test-image-medium.jpg);%7D%7D"
|
14
|
+
And I should see "@media%20screen%20and%20(min-width:401px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/photos/test-image/test-image-large.jpg);%7D%7D"
|
15
|
+
|
16
|
+
Scenario: Basic command with asset_host
|
17
|
+
Given a fixture app "automatic-clowncar-app"
|
18
|
+
And a file named "config.rb" with:
|
19
|
+
"""
|
20
|
+
activate :automatic_clowncar,
|
21
|
+
:sizes => {
|
22
|
+
:small => 200,
|
23
|
+
:medium => 400,
|
24
|
+
:large => 600
|
25
|
+
},
|
26
|
+
:namespace_directory => %w(photos)
|
27
|
+
activate :asset_host, :host => "http://localhost:4567/"
|
28
|
+
"""
|
29
|
+
And a file named "source/index.html.erb" with:
|
30
|
+
"""
|
31
|
+
<%= automatic_clowncar_tag "photos/test-image.jpg" %>
|
32
|
+
"""
|
33
|
+
And the Server is running at "automatic-clowncar-app"
|
34
|
+
When I go to "/index.html"
|
35
|
+
Then I should see "<object"
|
36
|
+
And I should see "@media%20screen%20and%20(max-width:200px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/photos/test-image/test-image-small.jpg);%7D%7D"
|
37
|
+
And I should see "@media%20screen%20and%20(min-width:201px)%20and%20(max-width:400px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/photos/test-image/test-image-medium.jpg);%7D%7D"
|
38
|
+
And I should see "@media%20screen%20and%20(min-width:401px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/photos/test-image/test-image-large.jpg);%7D%7D"
|
39
|
+
|
40
|
+
Scenario: With OldIE Fallback
|
41
|
+
Given a fixture app "automatic-clowncar-app"
|
42
|
+
And a file named "source/index.html.erb" with:
|
43
|
+
"""
|
44
|
+
<%= automatic_clowncar_tag "photos/test-image.jpg", :host => "http://localhost:4567/", :fallback => true %>
|
45
|
+
"""
|
46
|
+
And the Server is running at "automatic-clowncar-app"
|
47
|
+
When I go to "/index.html"
|
48
|
+
Then I should see "<object"
|
49
|
+
And I should see "@media%20screen%20and%20(max-width:200px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/photos/test-image/test-image-small.jpg);%7D%7D"
|
50
|
+
And I should see "@media%20screen%20and%20(min-width:201px)%20and%20(max-width:400px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/photos/test-image/test-image-medium.jpg);%7D%7D"
|
51
|
+
And I should see "@media%20screen%20and%20(min-width:401px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/photos/test-image/test-image-large.jpg);%7D%7D"
|
52
|
+
And I should see "<!--[if lte IE 8]>"
|
53
|
+
And I should see '<img src="/images/photos/test-image/test-image-small.jpg">'
|
54
|
+
And I should see "<![endif]-->"
|
55
|
+
|
@@ -0,0 +1,7 @@
|
|
1
|
+
ENV["TEST"] = "true"
|
2
|
+
ENV["AUTOLOAD_SPROCKETS"] = "false"
|
3
|
+
|
4
|
+
PROJECT_ROOT_PATH = File.dirname(File.dirname(File.dirname(__FILE__)))
|
5
|
+
require "middleman-core"
|
6
|
+
require "middleman-core/step_definitions"
|
7
|
+
require File.join(PROJECT_ROOT_PATH, 'lib', 'middleman-automatic-clowncar')
|
@@ -0,0 +1,22 @@
|
|
1
|
+
Feature: Generating thumbnails
|
2
|
+
|
3
|
+
Scenario: Basic useage during build
|
4
|
+
Given a fixture app "automatic-clowncar-app"
|
5
|
+
Given a successfully built app at "automatic-clowncar-app" with flags "--verbose"
|
6
|
+
When I cd to "build"
|
7
|
+
#Then the following files should not exist:
|
8
|
+
# | images/photos/test_image.jpg |
|
9
|
+
Then the following files should exist:
|
10
|
+
| images/photos/test-image/test-image-small.jpg |
|
11
|
+
| images/photos/test-image/test-image-medium.jpg |
|
12
|
+
| images/photos/test-image/test-image-large.jpg |
|
13
|
+
|
14
|
+
Scenario: Basic useage during preview
|
15
|
+
Given a fixture app "automatic-clowncar-app"
|
16
|
+
And the Server is running at "automatic-clowncar-app"
|
17
|
+
When I go to "/images/photos/test-image/test-image-small.jpg"
|
18
|
+
Then the content type should be "image/jpeg"
|
19
|
+
When I go to "/images/photos/test-image/test-image-medium.jpg"
|
20
|
+
Then the content type should be "image/jpeg"
|
21
|
+
When I go to "/images/photos/test-image/test-image-large.jpg"
|
22
|
+
Then the content type should be "image/jpeg"
|
Binary file
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= automatic_clowncar_tag "photos/test-image.jpg", :host => "http://localhost:4567/" %>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "middleman-core"
|
2
|
+
|
3
|
+
require "middleman-automatic-clowncar/version"
|
4
|
+
|
5
|
+
::Middleman::Extensions.register(:automatic_clowncar) do
|
6
|
+
require "middleman-automatic-clowncar/extension"
|
7
|
+
::Middleman::AutomaticClowncar::Extension
|
8
|
+
|
9
|
+
#require "middleman-automatic-clowncar/thumbnailer-extension"
|
10
|
+
#::Middleman::AutomaticClowncar::Thumbnailer
|
11
|
+
|
12
|
+
|
13
|
+
end
|
14
|
+
|
@@ -0,0 +1,317 @@
|
|
1
|
+
require 'middleman-core'
|
2
|
+
|
3
|
+
require 'middleman-automatic-clowncar/thumbnail-generator'
|
4
|
+
|
5
|
+
require 'fastimage'
|
6
|
+
|
7
|
+
module Middleman
|
8
|
+
module AutomaticClowncar
|
9
|
+
class Extension < Middleman::Extension
|
10
|
+
|
11
|
+
SVG_TEMPLATE = "<svg viewBox='0 0 ::width:: ::height::' preserveAspectRatio='xMidYMid meet' xmlns='http://www.w3.org/2000/svg'><style>svg{background-size:100% 100%;background-repeat:no-repeat;}::media_queries::</style></svg>"
|
12
|
+
|
13
|
+
option :sizes, {}, "The sizes of thumbnails to generate"
|
14
|
+
option :namespace_directory, ["**"], "The directories inside of images that should be clowncared."
|
15
|
+
option :filetypes, [:jpg, :jpeg, :png], "The types of files to use for automatic clowncaring."
|
16
|
+
|
17
|
+
cattr_accessor :options_hash
|
18
|
+
|
19
|
+
def initialize(app, options_hash={}, &block)
|
20
|
+
super
|
21
|
+
options_hash[:filetypes] ||= [:jpg, :jpeg, :png]
|
22
|
+
Extension.options_hash = options_hash
|
23
|
+
# Clowncar bits
|
24
|
+
require 'uri'
|
25
|
+
require 'pathname'
|
26
|
+
@ready = false
|
27
|
+
|
28
|
+
#Thumbnailer
|
29
|
+
app.after_configuration do
|
30
|
+
|
31
|
+
#stash the source images dir in options for the Rack middleware
|
32
|
+
Extension.options_hash[:images_source_dir] = File.join(source_dir, images_dir)
|
33
|
+
Extension.options_hash[:source_dir] = source_dir
|
34
|
+
|
35
|
+
sizes = Extension.options_hash[:sizes]
|
36
|
+
namespace = Extension.options_hash[:namespace_directory].join(',')
|
37
|
+
|
38
|
+
dir = Pathname.new(File.join(source_dir, images_dir))
|
39
|
+
glob = "#{dir}/#{namespace}/*.{#{Extension.options_hash[:filetypes].join(',')}}"
|
40
|
+
files = Dir[glob]
|
41
|
+
|
42
|
+
# don't build the files until after build
|
43
|
+
after_build do |builder|
|
44
|
+
files.each do |file|
|
45
|
+
path = file.gsub(source_dir, '')
|
46
|
+
specs = ThumbnailGenerator.specs(path, sizes)
|
47
|
+
ThumbnailGenerator.generate(source_dir, File.join(root, build_dir), path, specs)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
sitemap.register_resource_list_manipulator(:thumbnailer, SitemapExtension.new(self), true)
|
52
|
+
|
53
|
+
app.use Rack, Extension.options_hash
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def after_configuration
|
58
|
+
@ready = true
|
59
|
+
end
|
60
|
+
|
61
|
+
def is_relative_url?(path)
|
62
|
+
begin
|
63
|
+
uri = URI(path)
|
64
|
+
rescue URI::InvalidURIError
|
65
|
+
# Nothing we can do with it, it's not really a URI
|
66
|
+
return false
|
67
|
+
end
|
68
|
+
|
69
|
+
!uri.host
|
70
|
+
end
|
71
|
+
|
72
|
+
def get_image_path(name, path, is_relative, fallback_host)
|
73
|
+
puts "@@@@@@@ calling get_image_path for #{path}"
|
74
|
+
begin
|
75
|
+
uri = URI(path)
|
76
|
+
rescue URI::InvalidURIError
|
77
|
+
# Nothing we can do with it, it's not really a URI
|
78
|
+
return path
|
79
|
+
end
|
80
|
+
|
81
|
+
if uri.host
|
82
|
+
path
|
83
|
+
else
|
84
|
+
|
85
|
+
svg_path = File.join(File.dirname(name),File.basename(name,".*"), path)
|
86
|
+
|
87
|
+
if is_relative
|
88
|
+
url = app.asset_path(:images, svg_path)
|
89
|
+
|
90
|
+
if fallback_host &&is_relative_url?(url)
|
91
|
+
File.join(fallback_host, url)
|
92
|
+
else
|
93
|
+
url
|
94
|
+
end
|
95
|
+
else
|
96
|
+
svg_path
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
|
103
|
+
def generate_media_queries(name, sizes, is_relative, fallback_host)
|
104
|
+
output = []
|
105
|
+
|
106
|
+
if sizes.keys.length === 1
|
107
|
+
return "svg{background-image:url(#{get_image_path(name, sizes[sizes.keys.first], is_relative, fallback_host)});}"
|
108
|
+
end
|
109
|
+
|
110
|
+
previous_key = nil
|
111
|
+
sizes.keys.sort.each_with_index do |key, i|
|
112
|
+
line = ["@media screen and "]
|
113
|
+
|
114
|
+
if i == 0
|
115
|
+
line << "(max-width:#{key}px)"
|
116
|
+
elsif i == (sizes.keys.length - 1)
|
117
|
+
line << "(min-width:#{previous_key+1}px)"
|
118
|
+
else
|
119
|
+
line << "(min-width:#{previous_key+1}px) and (max-width:#{key}px)"
|
120
|
+
end
|
121
|
+
|
122
|
+
line << "{svg{background-image:url(#{get_image_path(name, sizes[key], is_relative, fallback_host)});}}"
|
123
|
+
|
124
|
+
output << line.join("")
|
125
|
+
previous_key = key
|
126
|
+
end
|
127
|
+
|
128
|
+
output.join("")
|
129
|
+
end
|
130
|
+
|
131
|
+
def get_image_sizes(name, options)
|
132
|
+
puts "getting images sizes for #{name}"
|
133
|
+
|
134
|
+
main_path = File.join(app.images_dir,name)
|
135
|
+
main_abs_path = File.join(app.source_dir,main_path)
|
136
|
+
|
137
|
+
extname = File.extname(name)
|
138
|
+
basename = File.basename(name, ".*")
|
139
|
+
|
140
|
+
return {} unless File.exist? main_abs_path
|
141
|
+
|
142
|
+
width, height = ::FastImage.size(main_abs_path, :raise_on_failure => true)
|
143
|
+
|
144
|
+
|
145
|
+
sizes = {}
|
146
|
+
Extension.options_hash[:sizes].each_pair do |sname,width|
|
147
|
+
sizes[width] = "#{basename}-#{sname}#{extname}"
|
148
|
+
end
|
149
|
+
|
150
|
+
puts "-"*30
|
151
|
+
puts [sizes, width, height]
|
152
|
+
[sizes, width, height]
|
153
|
+
end
|
154
|
+
|
155
|
+
|
156
|
+
def generate_svg(name, is_relative, options)
|
157
|
+
puts "name for generate_svg = #{name}"
|
158
|
+
puts "options for generate_svg = #{options}"
|
159
|
+
sizes, width, height = get_image_sizes(name, options)
|
160
|
+
|
161
|
+
fallback_host = false
|
162
|
+
if is_relative
|
163
|
+
test_path = app.asset_path(:images, "#{name}.svg")
|
164
|
+
if is_relative_url?(test_path)
|
165
|
+
if options.has_key?(:host)
|
166
|
+
fallback_host = options[:host]
|
167
|
+
else
|
168
|
+
warn "WARNING: Inline clowncar images require absolute paths. Please set a :host value"
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
media_queries = generate_media_queries(name, sizes, is_relative, fallback_host)
|
174
|
+
|
175
|
+
xml = SVG_TEMPLATE.dup
|
176
|
+
xml.sub!("::media_queries::", media_queries)
|
177
|
+
xml.sub!("::width::", width.to_s)
|
178
|
+
xml.sub!("::height::", height.to_s)
|
179
|
+
xml
|
180
|
+
end
|
181
|
+
|
182
|
+
def generate_clowncar(name, options={})
|
183
|
+
Extension.svg_files_to_generate << [name, options]
|
184
|
+
end
|
185
|
+
|
186
|
+
|
187
|
+
|
188
|
+
|
189
|
+
|
190
|
+
|
191
|
+
helpers do
|
192
|
+
def automatic_clowncar_tag(name, options={})
|
193
|
+
internal = ""
|
194
|
+
|
195
|
+
if options[:fallback]
|
196
|
+
|
197
|
+
fallback = File.basename thumbnail_url(name,:small)
|
198
|
+
fallback_path = extensions[:automatic_clowncar].get_image_path(name, fallback, true, false)
|
199
|
+
internal = %{<!--[if lte IE 8]><img src="#{fallback_path}"><![endif]-->}
|
200
|
+
end
|
201
|
+
|
202
|
+
if options.has_key?(:inline) && (options[:inline] === false)
|
203
|
+
url = asset_path(:images, "#{name}.svg")
|
204
|
+
%Q{<object type="image/svg+xml" data="#{url}">#{internal}</object>}
|
205
|
+
else
|
206
|
+
data = extensions[:automatic_clowncar].generate_svg(name, true, options)
|
207
|
+
%Q{<object type="image/svg+xml" data="data:image/svg+xml,#{::URI.escape(data)}">#{internal}</object>}
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def thumbnail_specs(image, name)
|
212
|
+
sizes = Extension.options_hash[:sizes]
|
213
|
+
ThumbnailGenerator.specs(image, sizes)
|
214
|
+
end
|
215
|
+
|
216
|
+
def thumbnail_url(image, name, options = {})
|
217
|
+
include_images_dir = options.delete :include_images_dir
|
218
|
+
|
219
|
+
url = thumbnail_specs(image, name)[name][:name]
|
220
|
+
url = File.join(images_dir, url) if include_images_dir
|
221
|
+
|
222
|
+
url
|
223
|
+
end
|
224
|
+
|
225
|
+
end # helpers
|
226
|
+
|
227
|
+
class SitemapExtension
|
228
|
+
def initialize(app)
|
229
|
+
@app = app
|
230
|
+
end
|
231
|
+
|
232
|
+
# Add sitemap resource for every image in the sprockets load path
|
233
|
+
def manipulate_resource_list(resources)
|
234
|
+
|
235
|
+
images_dir_abs = File.join(@app.source_dir, @app.images_dir)
|
236
|
+
|
237
|
+
images_dir = @app.images_dir
|
238
|
+
|
239
|
+
options = Extension.options_hash
|
240
|
+
sizes = options[:sizes]
|
241
|
+
namespace = options[:namespace_directory].join(',')
|
242
|
+
|
243
|
+
files = Dir["#{images_dir_abs}/#{namespace}/*.{#{Extension.options_hash[:filetypes].join(',')}}"]
|
244
|
+
|
245
|
+
resource_list = files.map do |file|
|
246
|
+
path = file.gsub(@app.source_dir + File::SEPARATOR, '')
|
247
|
+
specs = ::Middleman::AutomaticClowncar::ThumbnailGenerator.specs(path, sizes)
|
248
|
+
specs.map do |name, spec|
|
249
|
+
resource = nil
|
250
|
+
# puts "#{path}: #{spec[:name]}: #{file}"
|
251
|
+
resource = Middleman::Sitemap::Resource.new(@app.sitemap, spec[:name], file) unless name == :original
|
252
|
+
end
|
253
|
+
end.flatten.reject {|resource| resource.nil? }
|
254
|
+
|
255
|
+
resources + resource_list
|
256
|
+
end
|
257
|
+
end # SitemapExtension
|
258
|
+
|
259
|
+
|
260
|
+
# Rack middleware to convert images on the fly
|
261
|
+
class Rack
|
262
|
+
|
263
|
+
# Init
|
264
|
+
# @param [Class] app
|
265
|
+
# @param [Hash] options
|
266
|
+
def initialize(app, options={})
|
267
|
+
@app = app
|
268
|
+
@options = options
|
269
|
+
|
270
|
+
files = Dir["#{options[:images_source_dir]}/**/*.{#{options[:filetypes].join(',')}}"]
|
271
|
+
|
272
|
+
@original_map = ThumbnailGenerator.original_map_for_files(files, options[:sizes])
|
273
|
+
|
274
|
+
end
|
275
|
+
|
276
|
+
# Rack interface
|
277
|
+
# @param [Rack::Environmemt] env
|
278
|
+
# @return [Array]
|
279
|
+
def call(env)
|
280
|
+
status, headers, response = @app.call(env)
|
281
|
+
|
282
|
+
path = env["PATH_INFO"]
|
283
|
+
|
284
|
+
path_on_disk = File.join(@options[:source_dir], path)
|
285
|
+
|
286
|
+
#TODO: caching
|
287
|
+
if original_specs = @original_map[path_on_disk]
|
288
|
+
original_file = original_specs[:original]
|
289
|
+
spec = original_specs[:spec]
|
290
|
+
if spec.has_key? :sizes
|
291
|
+
image = ::Magick::Image.read(original_file).first
|
292
|
+
blob = nil
|
293
|
+
image.change_geometry(spec[:sizes]) do |cols, rows, img|
|
294
|
+
img = img.resize(cols, rows)
|
295
|
+
img = img.sharpen(0.5, 0.5)
|
296
|
+
blob = img.to_blob
|
297
|
+
end
|
298
|
+
|
299
|
+
unless blob.nil?
|
300
|
+
status = 200
|
301
|
+
headers["Content-Length"] = ::Rack::Utils.bytesize(blob).to_s
|
302
|
+
headers["Content-Type"] = image.mime_type
|
303
|
+
response = [blob]
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
[status, headers, response]
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
|
313
|
+
|
314
|
+
end # Extension
|
315
|
+
end # AutomaticClowncar
|
316
|
+
end # Middleman
|
317
|
+
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'RMagick'
|
2
|
+
|
3
|
+
module Middleman
|
4
|
+
module AutomaticClowncar
|
5
|
+
#actually creates the thumbnail names
|
6
|
+
class ThumbnailGenerator
|
7
|
+
class << self
|
8
|
+
|
9
|
+
def specs(origin, dimensions)
|
10
|
+
dir = File.dirname(origin)
|
11
|
+
filename = File.basename(origin,'.*')
|
12
|
+
ext = File.extname(origin)
|
13
|
+
|
14
|
+
dir = File.join(dir,filename)
|
15
|
+
|
16
|
+
ret = {original: {name: origin}}
|
17
|
+
|
18
|
+
dimensions.each do |name, dimension|
|
19
|
+
location = File.join(dir,"#{filename}-#{name}#{ext}")
|
20
|
+
ret[name] = {name:location , dimensions: dimension}
|
21
|
+
end
|
22
|
+
|
23
|
+
ret
|
24
|
+
end
|
25
|
+
|
26
|
+
def generate(source_dir, output_dir, origin, specs)
|
27
|
+
image = ::Magick::Image.read(File.join(source_dir, origin)).first
|
28
|
+
specs.each do |name, spec|
|
29
|
+
if spec.has_key? :dimensions then
|
30
|
+
image.change_geometry(spec[:dimensions]) do |cols, rows, img|
|
31
|
+
img = img.resize(cols, rows)
|
32
|
+
img = img.sharpen(0.5, 0.5)
|
33
|
+
img.write File.join(output_dir, spec[:name])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def original_map_for_files(files, specs)
|
40
|
+
map = files.inject({}) do |memo, file|
|
41
|
+
generated_specs = self.specs(file, specs)
|
42
|
+
generated_specs.each do |name, spec|
|
43
|
+
memo[spec[:name]] = {:original => generated_specs[:original][:name], :spec => spec}
|
44
|
+
end
|
45
|
+
memo
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'middleman-automatic-clowncar/thumbnail-generator'
|
2
|
+
|
3
|
+
module Middleman
|
4
|
+
module AutomaticClowncar
|
5
|
+
module Thumbnailer
|
6
|
+
class << self
|
7
|
+
|
8
|
+
attr_accessor :options
|
9
|
+
|
10
|
+
def registered(app, options={})
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
|
15
|
+
end
|
16
|
+
alias :included :registered
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require "middleman-automatic-clowncar"
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'middleman-automatic-clowncar/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "middleman-automatic-clowncar"
|
8
|
+
spec.version = MiddlemanAutomaticClowncar::VERSION
|
9
|
+
spec.authors = ["Jeremy Green"]
|
10
|
+
spec.email = ["jeremy@octolabs.com"]
|
11
|
+
spec.summary = %q{Automatically generated responsive images for middleman.}
|
12
|
+
spec.description = %q{Automatically generated responsive images for middleman.}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "middleman-core", "~> 3.2"
|
22
|
+
spec.add_dependency("rmagick", ["~> 2.13.0"])
|
23
|
+
spec.add_dependency "fastimage", "~> 1.5.5"
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
26
|
+
spec.add_development_dependency "rake"
|
27
|
+
spec.add_development_dependency "cucumber", "~> 1.3.10"
|
28
|
+
spec.add_development_dependency "aruba", "~> 0.5.1"
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: middleman-automatic-clowncar
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jeremy Green
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-01-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: middleman-core
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rmagick
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.13.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 2.13.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: fastimage
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.5.5
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.5.5
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.5'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.5'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: cucumber
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.3.10
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 1.3.10
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: aruba
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.5.1
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.5.1
|
111
|
+
description: Automatically generated responsive images for middleman.
|
112
|
+
email:
|
113
|
+
- jeremy@octolabs.com
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- ".gitignore"
|
119
|
+
- Gemfile
|
120
|
+
- LICENSE.txt
|
121
|
+
- README.md
|
122
|
+
- Rakefile
|
123
|
+
- features/clowncar_tag_build.feature
|
124
|
+
- features/clowncar_tag_preview.feature
|
125
|
+
- features/support/env.rb
|
126
|
+
- features/thumbnail_generation.feature
|
127
|
+
- fixtures/automatic-clowncar-app/config.rb
|
128
|
+
- fixtures/automatic-clowncar-app/source/images/photos/test-image.jpg
|
129
|
+
- fixtures/automatic-clowncar-app/source/index.html
|
130
|
+
- fixtures/automatic-clowncar-app/source/tag.html.erb
|
131
|
+
- lib/middleman-automatic-clowncar.rb
|
132
|
+
- lib/middleman-automatic-clowncar/extension.rb
|
133
|
+
- lib/middleman-automatic-clowncar/thumbnail-generator.rb
|
134
|
+
- lib/middleman-automatic-clowncar/thumbnailer-extension.rb
|
135
|
+
- lib/middleman-automatic-clowncar/version.rb
|
136
|
+
- lib/middleman_extension.rb
|
137
|
+
- middleman-automatic-clowncar.gemspec
|
138
|
+
homepage: ''
|
139
|
+
licenses:
|
140
|
+
- MIT
|
141
|
+
metadata: {}
|
142
|
+
post_install_message:
|
143
|
+
rdoc_options: []
|
144
|
+
require_paths:
|
145
|
+
- lib
|
146
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
147
|
+
requirements:
|
148
|
+
- - ">="
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: '0'
|
151
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
152
|
+
requirements:
|
153
|
+
- - ">="
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
version: '0'
|
156
|
+
requirements: []
|
157
|
+
rubyforge_project:
|
158
|
+
rubygems_version: 2.2.0.rc.1
|
159
|
+
signing_key:
|
160
|
+
specification_version: 4
|
161
|
+
summary: Automatically generated responsive images for middleman.
|
162
|
+
test_files:
|
163
|
+
- features/clowncar_tag_build.feature
|
164
|
+
- features/clowncar_tag_preview.feature
|
165
|
+
- features/support/env.rb
|
166
|
+
- features/thumbnail_generation.feature
|