middleman-automatic-clowncar 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ fixtures/*/build
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in middleman-automatic-clowncar.gemspec
4
+ gemspec
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"
@@ -0,0 +1,8 @@
1
+ activate :automatic_clowncar,
2
+ :sizes => {
3
+ :small => 200,
4
+ :medium => 400,
5
+ :large => 600
6
+ },
7
+ :namespace_directory => %w(photos)
8
+
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,3 @@
1
+ module MiddlemanAutomaticClowncar
2
+ VERSION = "0.0.1"
3
+ 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