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