middleman-clowncar 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b0ef235d8132cbbe805dfa221ba354daeca05033
4
+ data.tar.gz: 4f4b3f56912f9e3d3ffc89610b419d5756bfc608
5
+ SHA512:
6
+ metadata.gz: 8ce9bb579f9beae4e1f03957cc67fc6f47a84eb6eb88607e709bf71ab091a3313d8eb039ff0a05278268214085612dd6c46ae7daed8bf23c59e3d812989155af
7
+ data.tar.gz: 5a0145df3b5d61ded91c5bc6bbe25ba817390fd62861cb2cebe5ce5c2ddc39b0448d0d4d8b6617ec43ffd27050d0f9dcb83d79b82c32e522a66442a66a351d82
@@ -0,0 +1,9 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .rvmrc
6
+ .DS_Store
7
+ .rbenv-version
8
+ .ruby-version
9
+ /tmp
@@ -0,0 +1,7 @@
1
+ rvm:
2
+ - 1.9.3
3
+ - 2.0.0
4
+
5
+ script: "bundle exec rake test"
6
+
7
+ env: TEST=true
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in middleman-blog.gemspec
4
+ gemspec
5
+
6
+ group :development do
7
+ gem "rake", "~> 0.9.2"
8
+ gem "rdoc", "~> 3.9"
9
+ gem "yard", "~> 0.8.0"
10
+ end
11
+
12
+ group :test do
13
+ gem "cucumber", "~> 1.2.0"
14
+ gem "fivemat"
15
+ gem "aruba", "~> 0.4.11"
16
+ gem "rspec", "~> 2.7"
17
+ end
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010-2013 Thomas Reynolds
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,97 @@
1
+ # middleman-clowncar
2
+
3
+ middleman-clowncar is an extension for the [Middleman](http://middlemanapp.com) static site generator that makes it easy to generate [ClownCar](https://github.com/estelle/clowncar)-style responsive images.
4
+
5
+ # Install
6
+
7
+ In an existing Middleman project:
8
+ Add `middleman-clowncar` to your `Gemfile`
9
+ ```
10
+ gem "middleman-clowncar"
11
+ ```
12
+
13
+ Then open your `config.rb` and add:
14
+ ```
15
+ activate :clowncar
16
+ ```
17
+
18
+ # API
19
+
20
+ The extension adds two helper methods.
21
+
22
+ ## `generate_clowncar`
23
+
24
+ `generate_clowncar` can be used in your `config.rb` file to create a new `.svg` file in the sitemap which references the various image sizes you have available. You can then reference this `.svg` using a normal `image_tag`. Loading this SVG will be one request, then another will happen to load the correct size according to the `@media` query.
25
+
26
+ Here is an example:
27
+
28
+ ```
29
+ generate_clowncar "logo"
30
+ ```
31
+
32
+ This will look for a folder in `images/logo` and inspect the files within. It will create an SVG which loads the smallest possible image given the current image size. It will generate a file named: `images/logo-responsive.svg`
33
+
34
+ ## `clowncar_tag`
35
+
36
+ `clowncar_tag` is used in your templates to inline an SVG clowncar directly into a page. This approach will make sure only 1 request is ever made, for the correctly sized image only.
37
+
38
+ Here are some examples:
39
+
40
+ ```
41
+ <%= clowncar_tag "logo" %>
42
+ ```
43
+
44
+ This will look for a folder in `images/logo` and inspect the files within. It will create an SVG which loads the smallest possible image given the current image size. It will then, base-64 encode that SVG into an `object` tag.
45
+
46
+ ```
47
+ <%= clowncar_tag "logo" %>
48
+ ```
49
+
50
+ ## Remote Assets
51
+
52
+ Sometimes you don't actually have the resized files locally, but an external service will be handling this for you. In this case, you can pass your sizes and URLs using the `:sizes` parameter. Doing this will override any files you may have in a folder on disk. You'll also need to specify the `:width` and `:height` of the images.
53
+
54
+ ```
55
+ generate_clowncar "logo", :width => 768, :height => 480, :sizes => { 768 => "//remote.com/size-768", 1024 => "//remote.com/size-2024"}
56
+
57
+ # or
58
+
59
+ <%= clowncar_tag "logo", :width => 768, :height => 480, :sizes => { 768 => "//remote.com/size-768", 1024 => "//remote.com/size-2024"} %>
60
+ ```
61
+
62
+ ## OldIE
63
+
64
+ Old IE (6-7) doesn't support SVG, if you want to use a fallback image for these browsers, add the `:fallback` parameter to either API method and point it at the fallback image you wish to use, relative to the `logo` folder. This only works for the embedded method. So, if you had `images/logo/fallback.png` you'd use the following method:
65
+
66
+ ```
67
+ <%= clowncar_tag "logo", :fallback => "fallback.png" %>
68
+ ```
69
+
70
+ ## Build Status
71
+
72
+ [![Gem Version](https://badge.fury.io/rb/middleman-clowncar.png)](https://rubygems.org/gems/middleman-clowncar)
73
+ [![Build Status](https://travis-ci.org/middleman/middleman-clowncar.png)](http://travis-ci.org/middleman/middleman-clowncar)
74
+
75
+ # Community
76
+
77
+ The official community forum is available at:
78
+
79
+ http://forum.middlemanapp.com/
80
+
81
+ # Bug Reports
82
+
83
+ GitHub Issues are used for managing bug reports and feature requests. If you run into issues, please search the issues and submit new problems:
84
+
85
+ https://github.com/middleman/middleman-clowncar/issues
86
+
87
+ The best way to get quick responses to your issues and swift fixes to your bugs is to submit detailed bug reports, include test cases and respond to developer questions in a timely manner. Even better, if you know Ruby, you can submit Pull Requests containing Cucumber Features which describe how your feature should work or exploit the bug you are submitting.
88
+
89
+ # Support Us
90
+
91
+ [![Support via Gittip](https://rawgithub.com/twolfson/gittip-badge/0.1.0/dist/gittip.png)](https://www.gittip.com/tdreyno/)
92
+
93
+ [Support via Donation](https://spacebox.io/s/4dXbHBorC3)
94
+
95
+ ## License
96
+
97
+ Copyright (c) 2013 Thomas Reynolds. MIT Licensed, see [LICENSE](https://github.com/middleman/middleman-clowncar/blob/master/LICENSE.md) for details.
@@ -0,0 +1,22 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'cucumber/rake/task'
5
+
6
+ Cucumber::Rake::Task.new(:cucumber, 'Run features that should pass') do |t|
7
+ ENV["TEST"] = "true"
8
+
9
+ exempt_tags = ""
10
+ exempt_tags << "--tags ~@nojava" if RUBY_PLATFORM == "java"
11
+
12
+ t.cucumber_opts = "--color --tags ~@wip #{exempt_tags} --strict --format #{ENV['CUCUMBER_FORMAT'] || 'pretty'}"
13
+ end
14
+
15
+ require 'rake/clean'
16
+
17
+ task :test => ["cucumber"]
18
+
19
+ desc "Build HTML documentation"
20
+ task :doc do
21
+ sh 'bundle exec yard'
22
+ end
@@ -0,0 +1,163 @@
1
+ Feature: Generating SVG clowncars during preview mode
2
+
3
+ Scenario: Basic command
4
+ Given a fixture app "clowncar-app"
5
+ And a file named "source/index.html.erb" with:
6
+ """
7
+ <%= clowncar_tag "logo", :host => "http://localhost:4567/" %>
8
+ """
9
+ Given a successfully built app at "clowncar-app" with flags "--verbose"
10
+ When I cd to "build"
11
+ Then the following files should not exist:
12
+ | images/logo.svg |
13
+ Then the following files should exist:
14
+ | images/logo/small.png |
15
+ | images/logo/medium.png |
16
+ | images/logo/big.png |
17
+ Then the file "index.html" should contain "<object"
18
+ And the file "index.html" should contain "@media%20screen%20and%20(max-width:300px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo/small.png);%7D%7D"
19
+ And the file "index.html" should contain "@media%20screen%20and%20(min-width:301px)%20and%20(max-width:600px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo/medium.png);%7D%7D"
20
+ And the file "index.html" should contain "@media%20screen%20and%20(min-width:601px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo/big.png);%7D%7D"
21
+
22
+ Scenario: Basic command with asset_host
23
+ Given a fixture app "clowncar-app"
24
+ And a file named "config.rb" with:
25
+ """
26
+ activate :clowncar
27
+ activate :asset_host, :host => "http://localhost:4567/"
28
+ """
29
+ And a file named "source/index.html.erb" with:
30
+ """
31
+ <%= clowncar_tag "logo" %>
32
+ """
33
+ Given a successfully built app at "clowncar-app" with flags "--verbose"
34
+ When I cd to "build"
35
+ Then the following files should not exist:
36
+ | images/logo.svg |
37
+ Then the following files should exist:
38
+ | images/logo/small.png |
39
+ | images/logo/medium.png |
40
+ | images/logo/big.png |
41
+ Then the file "index.html" should contain "<object"
42
+ And the file "index.html" should contain "@media%20screen%20and%20(max-width:300px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo/small.png);%7D%7D"
43
+ And the file "index.html" should contain "@media%20screen%20and%20(min-width:301px)%20and%20(max-width:600px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo/medium.png);%7D%7D"
44
+ And the file "index.html" should contain "@media%20screen%20and%20(min-width:601px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo/big.png);%7D%7D"
45
+
46
+ Scenario: With OldIE Fallback
47
+ Given a fixture app "clowncar-app"
48
+ And a file named "source/index.html.erb" with:
49
+ """
50
+ <%= clowncar_tag "logo-with-fallback", :host => "http://localhost:4567/", :fallback => "fallback.png" %>
51
+ """
52
+ Given a successfully built app at "clowncar-app" with flags "--verbose"
53
+ When I cd to "build"
54
+ Then the following files should not exist:
55
+ | images/logo-with-fallback.svg |
56
+ Then the following files should exist:
57
+ | images/logo-with-fallback/small.png |
58
+ | images/logo-with-fallback/medium.png |
59
+ | images/logo-with-fallback/big.png |
60
+ Then the file "index.html" should contain "<object"
61
+ And the file "index.html" should contain "@media%20screen%20and%20(max-width:300px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo-with-fallback/small.png);%7D%7D"
62
+ And the file "index.html" should contain "@media%20screen%20and%20(min-width:301px)%20and%20(max-width:600px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo-with-fallback/medium.png);%7D%7D"
63
+ And the file "index.html" should contain "@media%20screen%20and%20(min-width:601px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo-with-fallback/big.png);%7D%7D"
64
+ And the file "index.html" should contain "<!--[if lte IE 8]>"
65
+ And the file "index.html" should contain '<img src="/images/logo-with-fallback/fallback.png">'
66
+ And the file "index.html" should contain "<![endif]-->"
67
+
68
+ Scenario: With remote OldIE Fallback
69
+ Given a fixture app "clowncar-app"
70
+ And a file named "source/index.html.erb" with:
71
+ """
72
+ <%= clowncar_tag "logo", :host => "http://localhost:4567/", :fallback => "http://example.com/fallback.png" %>
73
+ """
74
+ Given a successfully built app at "clowncar-app" with flags "--verbose"
75
+ When I cd to "build"
76
+ Then the following files should not exist:
77
+ | images/logo.svg |
78
+ Then the following files should exist:
79
+ | images/logo/small.png |
80
+ | images/logo/medium.png |
81
+ | images/logo/big.png |
82
+ Then the file "index.html" should contain "<object"
83
+ And the file "index.html" should contain "@media%20screen%20and%20(max-width:300px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo/small.png);%7D%7D"
84
+ And the file "index.html" should contain "@media%20screen%20and%20(min-width:301px)%20and%20(max-width:600px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo/medium.png);%7D%7D"
85
+ And the file "index.html" should contain "@media%20screen%20and%20(min-width:601px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo/big.png);%7D%7D"
86
+ And the file "index.html" should contain "<!--[if lte IE 8]>"
87
+ And the file "index.html" should contain '<img src="http://example.com/fallback.png">'
88
+ And the file "index.html" should contain "<![endif]-->"
89
+
90
+ Scenario: Reference rather than inline
91
+ Given a fixture app "clowncar-app"
92
+ And a file named "config.rb" with:
93
+ """
94
+ activate :clowncar
95
+ generate_clowncar "logo"
96
+ """
97
+ And a file named "source/index.html.erb" with:
98
+ """
99
+ <%= clowncar_tag "logo", :inline => false %>
100
+ """
101
+ Given a successfully built app at "clowncar-app" with flags "--verbose"
102
+ When I cd to "build"
103
+ Then the following files should exist:
104
+ | images/logo.svg |
105
+ | images/logo/small.png |
106
+ | images/logo/medium.png |
107
+ | images/logo/big.png |
108
+ Then the file "index.html" should contain '<object type="image/svg+xml" data="/images/logo.svg"></object>'
109
+
110
+ Scenario: With custom sizes locally
111
+ Given a fixture app "clowncar-app"
112
+ And a file named "source/index.html.erb" with:
113
+ """
114
+ <%= clowncar_tag "logo", :host => "http://localhost:4567/", :sizes => { 768 => "big.png", 1024 => "medium.png", 1280 => "small.png" } %>
115
+ """
116
+ Given a successfully built app at "clowncar-app" with flags "--verbose"
117
+ When I cd to "build"
118
+ Then the following files should not exist:
119
+ | images/logo.svg |
120
+ Then the following files should exist:
121
+ | images/logo/small.png |
122
+ | images/logo/medium.png |
123
+ | images/logo/big.png |
124
+ Then the file "index.html" should contain "<object"
125
+ And the file "index.html" should contain "@media%20screen%20and%20(max-width:768px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo/big.png);%7D%7D"
126
+ And the file "index.html" should contain "@media%20screen%20and%20(min-width:769px)%20and%20(max-width:1024px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo/medium.png);%7D%7D"
127
+ And the file "index.html" should contain "@media%20screen%20and%20(min-width:1025px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo/small.png);%7D%7D"
128
+
129
+ Scenario: With single size
130
+ Given a fixture app "clowncar-app"
131
+ And a file named "source/index.html.erb" with:
132
+ """
133
+ <%= clowncar_tag "logo", :host => "http://localhost:4567/", :sizes => { 768 => "big.png" } %>
134
+ """
135
+ Given a successfully built app at "clowncar-app" with flags "--verbose"
136
+ When I cd to "build"
137
+ Then the following files should not exist:
138
+ | images/logo.svg |
139
+ Then the following files should exist:
140
+ | images/logo/small.png |
141
+ | images/logo/medium.png |
142
+ | images/logo/big.png |
143
+ Then the file "index.html" should contain "<object"
144
+ And the file "index.html" should contain "svg%7Bbackground-image:url(http://localhost:4567/images/logo/big.png);%7D"
145
+
146
+ Scenario: With custom sizes remotely
147
+ Given a fixture app "clowncar-app"
148
+ And a file named "source/index.html.erb" with:
149
+ """
150
+ <%= clowncar_tag "logo", :sizes => { 333 => "//remote.com/size-333", 768 => "//remote.com/size-768", 1024 => "//remote.com/size-1024" } %>
151
+ """
152
+ Given a successfully built app at "clowncar-app" with flags "--verbose"
153
+ When I cd to "build"
154
+ Then the following files should not exist:
155
+ | images/logo.svg |
156
+ Then the following files should exist:
157
+ | images/logo/small.png |
158
+ | images/logo/medium.png |
159
+ | images/logo/big.png |
160
+ Then the file "index.html" should contain "<object"
161
+ And the file "index.html" should contain "@media%20screen%20and%20(max-width:333px)%7Bsvg%7Bbackground-image:url(//remote.com/size-333);%7D%7D"
162
+ And the file "index.html" should contain "@media%20screen%20and%20(min-width:334px)%20and%20(max-width:768px)%7Bsvg%7Bbackground-image:url(//remote.com/size-768);%7D%7D"
163
+ And the file "index.html" should contain "@media%20screen%20and%20(min-width:769px)%7Bsvg%7Bbackground-image:url(//remote.com/size-1024);%7D%7D"
@@ -0,0 +1,101 @@
1
+ Feature: Generating SVG clowncars during preview mode
2
+
3
+ Scenario: Basic command
4
+ Given a fixture app "clowncar-app"
5
+ And a file named "source/index.html.erb" with:
6
+ """
7
+ <%= clowncar_tag "logo", :host => "http://localhost:4567/" %>
8
+ """
9
+ And the Server is running at "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:300px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo/small.png);%7D%7D"
13
+ And I should see "@media%20screen%20and%20(min-width:301px)%20and%20(max-width:600px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo/medium.png);%7D%7D"
14
+ And I should see "@media%20screen%20and%20(min-width:601px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo/big.png);%7D%7D"
15
+
16
+ Scenario: Basic command with asset_host
17
+ Given a fixture app "clowncar-app"
18
+ And a file named "config.rb" with:
19
+ """
20
+ activate :clowncar
21
+ activate :asset_host, :host => "http://localhost:4567/"
22
+ """
23
+ And a file named "source/index.html.erb" with:
24
+ """
25
+ <%= clowncar_tag "logo" %>
26
+ """
27
+ And the Server is running at "clowncar-app"
28
+ When I go to "/index.html"
29
+ Then I should see "<object"
30
+ And I should see "@media%20screen%20and%20(max-width:300px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo/small.png);%7D%7D"
31
+ And I should see "@media%20screen%20and%20(min-width:301px)%20and%20(max-width:600px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo/medium.png);%7D%7D"
32
+ And I should see "@media%20screen%20and%20(min-width:601px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo/big.png);%7D%7D"
33
+
34
+ Scenario: With OldIE Fallback
35
+ Given a fixture app "clowncar-app"
36
+ And a file named "source/index.html.erb" with:
37
+ """
38
+ <%= clowncar_tag "logo-with-fallback", :host => "http://localhost:4567/", :fallback => "fallback.png" %>
39
+ """
40
+ And the Server is running at "clowncar-app"
41
+ When I go to "/index.html"
42
+ Then I should see "<object"
43
+ And I should see "@media%20screen%20and%20(max-width:300px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo-with-fallback/small.png);%7D%7D"
44
+ And I should see "@media%20screen%20and%20(min-width:301px)%20and%20(max-width:600px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo-with-fallback/medium.png);%7D%7D"
45
+ And I should see "@media%20screen%20and%20(min-width:601px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo-with-fallback/big.png);%7D%7D"
46
+ And I should see "<!--[if lte IE 8]>"
47
+ And I should see '<img src="/images/logo-with-fallback/fallback.png">'
48
+ And I should see "<![endif]-->"
49
+
50
+ Scenario: With remote OldIE Fallback
51
+ Given a fixture app "clowncar-app"
52
+ And a file named "source/index.html.erb" with:
53
+ """
54
+ <%= clowncar_tag "logo", :host => "http://localhost:4567/", :fallback => "http://example.com/fallback.png" %>
55
+ """
56
+ And the Server is running at "clowncar-app"
57
+ When I go to "/index.html"
58
+ Then I should see "<object"
59
+ And I should see "@media%20screen%20and%20(max-width:300px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo/small.png);%7D%7D"
60
+ And I should see "@media%20screen%20and%20(min-width:301px)%20and%20(max-width:600px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo/medium.png);%7D%7D"
61
+ And I should see "@media%20screen%20and%20(min-width:601px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo/big.png);%7D%7D"
62
+ And I should see "<!--[if lte IE 8]>"
63
+ And I should see '<img src="http://example.com/fallback.png">'
64
+ And I should see "<![endif]-->"
65
+
66
+ Scenario: With custom sizes locally
67
+ Given a fixture app "clowncar-app"
68
+ And a file named "source/index.html.erb" with:
69
+ """
70
+ <%= clowncar_tag "logo", :host => "http://localhost:4567/", :sizes => { 768 => "big.png", 1024 => "medium.png", 1280 => "small.png" } %>
71
+ """
72
+ And the Server is running at "clowncar-app"
73
+ When I go to "/index.html"
74
+ Then I should see "<object"
75
+ And I should see "@media%20screen%20and%20(max-width:768px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo/big.png);%7D%7D"
76
+ And I should see "@media%20screen%20and%20(min-width:769px)%20and%20(max-width:1024px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo/medium.png);%7D%7D"
77
+ And I should see "@media%20screen%20and%20(min-width:1025px)%7Bsvg%7Bbackground-image:url(http://localhost:4567/images/logo/small.png);%7D%7D"
78
+
79
+ Scenario: With single size
80
+ Given a fixture app "clowncar-app"
81
+ And a file named "source/index.html.erb" with:
82
+ """
83
+ <%= clowncar_tag "logo", :host => "http://localhost:4567/", :sizes => { 768 => "big.png" } %>
84
+ """
85
+ And the Server is running at "clowncar-app"
86
+ When I go to "/index.html"
87
+ Then I should see "<object"
88
+ And I should see "svg%7Bbackground-image:url(http://localhost:4567/images/logo/big.png);%7D"
89
+
90
+ Scenario: With custom sizes remotely
91
+ Given a fixture app "clowncar-app"
92
+ And a file named "source/index.html.erb" with:
93
+ """
94
+ <%= clowncar_tag "logo", :sizes => { 333 => "//remote.com/size-333", 768 => "//remote.com/size-768", 1024 => "//remote.com/size-1024" } %>
95
+ """
96
+ And the Server is running at "clowncar-app"
97
+ When I go to "/index.html"
98
+ Then I should see "<object"
99
+ And I should see "@media%20screen%20and%20(max-width:333px)%7Bsvg%7Bbackground-image:url(//remote.com/size-333);%7D%7D"
100
+ And I should see "@media%20screen%20and%20(min-width:334px)%20and%20(max-width:768px)%7Bsvg%7Bbackground-image:url(//remote.com/size-768);%7D%7D"
101
+ And I should see "@media%20screen%20and%20(min-width:769px)%7Bsvg%7Bbackground-image:url(//remote.com/size-1024);%7D%7D"
@@ -0,0 +1,75 @@
1
+ Feature: Generating SVG clowncars during build mode
2
+
3
+ Scenario: Basic command
4
+ Given a fixture app "clowncar-app"
5
+ And a file named "config.rb" with:
6
+ """
7
+ activate :clowncar
8
+ generate_clowncar "logo"
9
+ """
10
+ Given a successfully built app at "clowncar-app"
11
+ When I cd to "build"
12
+ Then the following files should exist:
13
+ | images/logo.svg |
14
+ | images/logo/small.png |
15
+ | images/logo/medium.png |
16
+ | images/logo/big.png |
17
+ Then the file "images/logo.svg" should contain "<svg"
18
+ And the file "images/logo.svg" should contain "@media screen and (max-width:300px){svg{background-image:url(logo/small.png);}}"
19
+ And the file "images/logo.svg" should contain "@media screen and (min-width:301px) and (max-width:600px){svg{background-image:url(logo/medium.png);}}"
20
+ And the file "images/logo.svg" should contain "@media screen and (min-width:601px){svg{background-image:url(logo/big.png);}}"
21
+
22
+ Scenario: With custom sizes locally
23
+ Given a fixture app "clowncar-app"
24
+ And a file named "config.rb" with:
25
+ """
26
+ activate :clowncar
27
+ generate_clowncar "logo", :sizes => { 768 => "big.png", 1024 => "medium.png", 1280 => "small.png" }
28
+ """
29
+ Given a successfully built app at "clowncar-app"
30
+ When I cd to "build"
31
+ Then the following files should exist:
32
+ | images/logo.svg |
33
+ | images/logo/small.png |
34
+ | images/logo/medium.png |
35
+ | images/logo/big.png |
36
+ Then the file "images/logo.svg" should contain "<svg"
37
+ And the file "images/logo.svg" should contain "@media screen and (max-width:768px){svg{background-image:url(logo/big.png);}}"
38
+ And the file "images/logo.svg" should contain "@media screen and (min-width:769px) and (max-width:1024px){svg{background-image:url(logo/medium.png);}}"
39
+ And the file "images/logo.svg" should contain "@media screen and (min-width:1025px){svg{background-image:url(logo/small.png);}}"
40
+
41
+ Scenario: With single size
42
+ Given a fixture app "clowncar-app"
43
+ And a file named "config.rb" with:
44
+ """
45
+ activate :clowncar
46
+ generate_clowncar "logo", :sizes => { 768 => "big.png" }
47
+ """
48
+ Given a successfully built app at "clowncar-app"
49
+ When I cd to "build"
50
+ Then the following files should exist:
51
+ | images/logo.svg |
52
+ | images/logo/small.png |
53
+ | images/logo/medium.png |
54
+ | images/logo/big.png |
55
+ Then the file "images/logo.svg" should contain "<svg"
56
+ And the file "images/logo.svg" should contain "svg{background-image:url(logo/big.png);}"
57
+
58
+ Scenario: With custom sizes remotely
59
+ Given a fixture app "clowncar-app"
60
+ And a file named "config.rb" with:
61
+ """
62
+ activate :clowncar
63
+ generate_clowncar "logo", :sizes => { 333 => "//remote.com/size-333", 768 => "//remote.com/size-768", 1024 => "//remote.com/size-1024" }
64
+ """
65
+ Given a successfully built app at "clowncar-app"
66
+ When I cd to "build"
67
+ Then the following files should exist:
68
+ | images/logo.svg |
69
+ | images/logo/small.png |
70
+ | images/logo/medium.png |
71
+ | images/logo/big.png |
72
+ Then the file "images/logo.svg" should contain "<svg"
73
+ And the file "images/logo.svg" should contain "@media screen and (max-width:333px){svg{background-image:url(//remote.com/size-333);}}"
74
+ And the file "images/logo.svg" should contain "@media screen and (min-width:334px) and (max-width:768px){svg{background-image:url(//remote.com/size-768);}}"
75
+ And the file "images/logo.svg" should contain "@media screen and (min-width:769px){svg{background-image:url(//remote.com/size-1024);}}"
@@ -0,0 +1,55 @@
1
+ Feature: Generating SVG clowncars during preview mode
2
+
3
+ Scenario: Basic command
4
+ Given a fixture app "clowncar-app"
5
+ And a file named "config.rb" with:
6
+ """
7
+ activate :clowncar
8
+ generate_clowncar "logo"
9
+ """
10
+ And the Server is running at "clowncar-app"
11
+ When I go to "/images/logo.svg"
12
+ Then I should see "<svg"
13
+ And I should see "@media screen and (max-width:300px){svg{background-image:url(logo/small.png);}}"
14
+ And I should see "@media screen and (min-width:301px) and (max-width:600px){svg{background-image:url(logo/medium.png);}}"
15
+ And I should see "@media screen and (min-width:601px){svg{background-image:url(logo/big.png);}}"
16
+
17
+ Scenario: With custom sizes locally
18
+ Given a fixture app "clowncar-app"
19
+ And a file named "config.rb" with:
20
+ """
21
+ activate :clowncar
22
+ generate_clowncar "logo", :sizes => { 768 => "big.png", 1024 => "medium.png", 1280 => "small.png" }
23
+ """
24
+ And the Server is running at "clowncar-app"
25
+ When I go to "/images/logo.svg"
26
+ Then I should see "<svg"
27
+ And I should see "@media screen and (max-width:768px){svg{background-image:url(logo/big.png);}}"
28
+ And I should see "@media screen and (min-width:769px) and (max-width:1024px){svg{background-image:url(logo/medium.png);}}"
29
+ And I should see "@media screen and (min-width:1025px){svg{background-image:url(logo/small.png);}}"
30
+
31
+ Scenario: With single size
32
+ Given a fixture app "clowncar-app"
33
+ And a file named "config.rb" with:
34
+ """
35
+ activate :clowncar
36
+ generate_clowncar "logo", :sizes => { 768 => "big.png" }
37
+ """
38
+ And the Server is running at "clowncar-app"
39
+ When I go to "/images/logo.svg"
40
+ Then I should see "<svg"
41
+ And I should see "svg{background-image:url(logo/big.png);}"
42
+
43
+ Scenario: With custom sizes remotely
44
+ Given a fixture app "clowncar-app"
45
+ And a file named "config.rb" with:
46
+ """
47
+ activate :clowncar
48
+ generate_clowncar "logo", :sizes => { 333 => "//remote.com/size-333", 768 => "//remote.com/size-768", 1024 => "//remote.com/size-1024" }
49
+ """
50
+ And the Server is running at "clowncar-app"
51
+ When I go to "/images/logo.svg"
52
+ Then I should see "<svg"
53
+ And I should see "@media screen and (max-width:333px){svg{background-image:url(//remote.com/size-333);}}"
54
+ And I should see "@media screen and (min-width:334px) and (max-width:768px){svg{background-image:url(//remote.com/size-768);}}"
55
+ And I should see "@media screen and (min-width:769px){svg{background-image:url(//remote.com/size-1024);}}"
@@ -0,0 +1,6 @@
1
+ PROJECT_ROOT_PATH = File.dirname(File.dirname(File.dirname(__FILE__)))
2
+ ENV['TEST'] = 'true'
3
+ require "middleman-core"
4
+ require "middleman-core/step_definitions"
5
+ require File.join(PROJECT_ROOT_PATH, 'lib', 'middleman-clowncar')
6
+
@@ -0,0 +1 @@
1
+ activate :clowncar
@@ -0,0 +1,7 @@
1
+ require "middleman-core"
2
+ require "middleman-clowncar/version"
3
+
4
+ ::Middleman::Extensions.register(:clowncar) do
5
+ require "middleman-clowncar/extension"
6
+ ::Middleman::ClownCarExtension
7
+ end
@@ -0,0 +1,215 @@
1
+ module Middleman
2
+ class ClownCarExtension < ::Middleman::Extension
3
+
4
+ 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>"
5
+
6
+ def initialize(app, options_hash={})
7
+ super
8
+
9
+ require 'uri'
10
+ require 'pathname'
11
+ require File.join(File.dirname(__FILE__), 'fastimage')
12
+
13
+ @svg_files_to_generate = []
14
+
15
+ @ready = false
16
+
17
+ app.send :include, ClownCarConfigAPI
18
+ end
19
+
20
+ def after_configuration
21
+ @ready = true
22
+ end
23
+
24
+ def is_relative_url?(path)
25
+ begin
26
+ uri = URI(path)
27
+ rescue URI::InvalidURIError
28
+ # Nothing we can do with it, it's not really a URI
29
+ return false
30
+ end
31
+
32
+ !uri.host
33
+ end
34
+
35
+ def get_image_path(name, path, is_relative, fallback_host)
36
+ begin
37
+ uri = URI(path)
38
+ rescue URI::InvalidURIError
39
+ # Nothing we can do with it, it's not really a URI
40
+ return path
41
+ end
42
+
43
+ if uri.host
44
+ path
45
+ else
46
+ svg_path = File.join(name, path)
47
+
48
+ if is_relative
49
+ url = app.asset_path(:images, svg_path)
50
+
51
+ if fallback_host &&is_relative_url?(url)
52
+ File.join(fallback_host, url)
53
+ else
54
+ url
55
+ end
56
+ else
57
+ svg_path
58
+ end
59
+ end
60
+ end
61
+
62
+ def generate_media_queries(name, sizes, is_relative, fallback_host)
63
+ output = []
64
+
65
+ if sizes.keys.length === 1
66
+ return "svg{background-image:url(#{get_image_path(name, sizes[sizes.keys.first], is_relative, fallback_host)});}"
67
+ end
68
+
69
+ previous_key = nil
70
+ sizes.keys.sort.each_with_index do |key, i|
71
+ line = ["@media screen and "]
72
+
73
+ if i == 0
74
+ line << "(max-width:#{key}px)"
75
+ elsif i == (sizes.keys.length - 1)
76
+ line << "(min-width:#{previous_key+1}px)"
77
+ else
78
+ line << "(min-width:#{previous_key+1}px) and (max-width:#{key}px)"
79
+ end
80
+
81
+ line << "{svg{background-image:url(#{get_image_path(name, sizes[key], is_relative, fallback_host)});}}"
82
+
83
+ output << line.join("")
84
+ previous_key = key
85
+ end
86
+
87
+ output.join("")
88
+ end
89
+
90
+ def get_image_sizes(name, options)
91
+ p = Pathname(app.source_dir) + Pathname(File.join(app.images_dir, name.to_s))
92
+
93
+ return {} unless p.exist?
94
+
95
+ width = nil
96
+ height = nil
97
+
98
+ sizes = p.children.inject({}) do |sum, path|
99
+ begin
100
+ width, height = ::FastImage.size(path.to_s, :raise_on_failure => true)
101
+ rel_path = path.relative_path_from(p).to_s
102
+
103
+ unless rel_path === options[:fallback]
104
+ sum[width] = path.relative_path_from(p).to_s
105
+ end
106
+ rescue FastImage::UnknownImageType
107
+ # No message, it's just not supported
108
+ rescue
109
+ warn "Couldn't determine dimensions for image #{path}: #{$!.message}"
110
+ end
111
+
112
+ sum
113
+ end
114
+
115
+ [sizes, width, height]
116
+ end
117
+
118
+ def generate_svg(name, is_relative, options)
119
+ if options[:sizes]
120
+ sizes = options[:sizes]
121
+ width = options[:width]
122
+ height = options[:height]
123
+ else
124
+ sizes, width, height = get_image_sizes(name, options)
125
+ end
126
+
127
+ fallback_host = false
128
+ if is_relative
129
+ test_path = app.asset_path(:images, "#{name}.svg")
130
+ if is_relative_url?(test_path)
131
+ if options.has_key?(:host)
132
+ fallback_host = options[:host]
133
+ else
134
+ warn "WARNING: Inline clowncar images require absolute paths. Please set a :host value"
135
+ end
136
+ end
137
+ end
138
+
139
+ media_queries = generate_media_queries(name, sizes, is_relative, fallback_host)
140
+
141
+ xml = SVG_TEMPLATE.dup
142
+ xml.sub!("::media_queries::", media_queries)
143
+ xml.sub!("::width::", width.to_s)
144
+ xml.sub!("::height::", height.to_s)
145
+ xml
146
+ end
147
+
148
+ def generate_clowncar(name, options={})
149
+ @svg_files_to_generate << [name, options]
150
+ end
151
+
152
+ def manipulate_resource_list(resources)
153
+ return resources unless @ready
154
+
155
+ resources + @svg_files_to_generate.map do |name, options|
156
+ file_name = File.join(app.images_dir, "#{name}.svg")
157
+ output = generate_svg(name, false, options)
158
+ ClownCarResource.new(app.sitemap, file_name, output)
159
+ end
160
+ end
161
+
162
+ class ClownCarResource < ::Middleman::Sitemap::Resource
163
+ def initialize(store, path, svg=nil)
164
+ super(store, path, nil)
165
+
166
+ @svg = svg
167
+ end
168
+
169
+ def render(opts={}, locs={}, &block)
170
+ @svg
171
+ end
172
+
173
+ def ignored?
174
+ false
175
+ end
176
+
177
+ def raw_data
178
+ {}
179
+ end
180
+
181
+ def metadata
182
+ @local_metadata
183
+ end
184
+
185
+ def binary?
186
+ false
187
+ end
188
+ end
189
+
190
+ helpers do
191
+ def clowncar_tag(name, options={})
192
+ internal = ""
193
+
194
+ if options[:fallback]
195
+ fallback_path = extensions[:clowncar].get_image_path(name, options[:fallback], true, false)
196
+ internal = %{<!--[if lte IE 8]><img src="#{fallback_path}"><![endif]-->}
197
+ end
198
+
199
+ if options.has_key?(:inline) && (options[:inline] === false)
200
+ url = asset_path(:images, "#{name}.svg")
201
+ %Q{<object type="image/svg+xml" data="#{url}">#{internal}</object>}
202
+ else
203
+ data = extensions[:clowncar].generate_svg(name, true, options)
204
+ %Q{<object type="image/svg+xml" data="data:image/svg+xml,#{::URI.escape(data)}">#{internal}</object>}
205
+ end
206
+ end
207
+ end
208
+
209
+ module ClownCarConfigAPI
210
+ def generate_clowncar(name, options={})
211
+ extensions[:clowncar].generate_clowncar(name, options)
212
+ end
213
+ end
214
+ end
215
+ end
@@ -0,0 +1,287 @@
1
+ # FastImage finds the size or type of an image given its uri.
2
+ # It is careful to only fetch and parse as much of the image as is needed to determine the result.
3
+ # It does this by using a feature of Net::HTTP that yields strings from the resource being fetched
4
+ # as soon as the packets arrive.
5
+ #
6
+ # No external libraries such as ImageMagick are used here, this is a very lightweight solution to
7
+ # finding image information.
8
+ #
9
+ # FastImage knows about GIF, JPEG, BMP and PNG files.
10
+ #
11
+ # FastImage can also read files from the local filesystem by supplying the path instead of a uri.
12
+ # In this case FastImage uses the open-uri library to read the file in chunks of 256 bytes until
13
+ # it has enough. This is possibly a useful bandwidth-saving feature if the file is on a network
14
+ # attached disk rather than truly local.
15
+ #
16
+ # === Examples
17
+ # require 'fastimage'
18
+ #
19
+ # FastImage.size("http://stephensykes.com/images/ss.com_x.gif")
20
+ # => [266, 56]
21
+ # FastImage.type("http://stephensykes.com/images/pngimage")
22
+ # => :png
23
+ # FastImage.type("/some/local/file.gif")
24
+ # => :gif
25
+ #
26
+ # === References
27
+ # * http://snippets.dzone.com/posts/show/805
28
+ # * http://www.anttikupila.com/flash/getting-jpg-dimensions-with-as3-without-loading-the-entire-file/
29
+ # * http://pennysmalls.com/2008/08/19/find-jpeg-dimensions-fast-in-ruby/
30
+ # * http://imagesize.rubyforge.org/
31
+ #
32
+ require 'net/https'
33
+ require 'open-uri'
34
+
35
+ class FastImage
36
+ attr_reader :size, :type
37
+
38
+ class FastImageException < StandardError # :nodoc:
39
+ end
40
+ class MoreCharsNeeded < FastImageException # :nodoc:
41
+ end
42
+ class UnknownImageType < FastImageException # :nodoc:
43
+ end
44
+ class ImageFetchFailure < FastImageException # :nodoc:
45
+ end
46
+ class SizeNotFound < FastImageException # :nodoc:
47
+ end
48
+
49
+ DefaultTimeout = 2
50
+
51
+ LocalFileChunkSize = 256
52
+
53
+ # Returns an array containing the width and height of the image.
54
+ # It will return nil if the image could not be fetched, or if the image type was not recognised.
55
+ #
56
+ # By default there is a timeout of 2 seconds for opening and reading from a remote server.
57
+ # This can be changed by passing a :timeout => number_of_seconds in the options.
58
+ #
59
+ # If you wish FastImage to raise if it cannot size the image for any reason, then pass
60
+ # :raise_on_failure => true in the options.
61
+ #
62
+ # FastImage knows about GIF, JPEG, BMP and PNG files.
63
+ #
64
+ # === Example
65
+ #
66
+ # require 'fastimage'
67
+ #
68
+ # FastImage.size("http://stephensykes.com/images/ss.com_x.gif")
69
+ # => [266, 56]
70
+ # FastImage.size("http://stephensykes.com/images/pngimage")
71
+ # => [16, 16]
72
+ # FastImage.size("http://farm4.static.flickr.com/3023/3047236863_9dce98b836.jpg")
73
+ # => [500, 375]
74
+ # FastImage.size("http://www-ece.rice.edu/~wakin/images/lena512.bmp")
75
+ # => [512, 512]
76
+ # FastImage.size("test/fixtures/test.jpg")
77
+ # => [882, 470]
78
+ # FastImage.size("http://pennysmalls.com/does_not_exist")
79
+ # => nil
80
+ # FastImage.size("http://pennysmalls.com/does_not_exist", :raise_on_failure=>true)
81
+ # => raises FastImage::ImageFetchFailure
82
+ # FastImage.size("http://stephensykes.com/favicon.ico", :raise_on_failure=>true)
83
+ # => raises FastImage::UnknownImageType
84
+ # FastImage.size("http://stephensykes.com/favicon.ico", :raise_on_failure=>true, :timeout=>0.01)
85
+ # => raises FastImage::ImageFetchFailure
86
+ # FastImage.size("http://stephensykes.com/images/faulty.jpg", :raise_on_failure=>true)
87
+ # => raises FastImage::SizeNotFound
88
+ #
89
+ # === Supported options
90
+ # [:timeout]
91
+ # Overrides the default timeout of 2 seconds. Applies both to reading from and opening the http connection.
92
+ # [:raise_on_failure]
93
+ # If set to true causes an exception to be raised if the image size cannot be found for any reason.
94
+ #
95
+ def self.size(uri, options={})
96
+ new(uri, options).size
97
+ end
98
+
99
+ # Returns an symbol indicating the image type fetched from a uri.
100
+ # It will return nil if the image could not be fetched, or if the image type was not recognised.
101
+ #
102
+ # By default there is a timeout of 2 seconds for opening and reading from a remote server.
103
+ # This can be changed by passing a :timeout => number_of_seconds in the options.
104
+ #
105
+ # If you wish FastImage to raise if it cannot find the type of the image for any reason, then pass
106
+ # :raise_on_failure => true in the options.
107
+ #
108
+ # === Example
109
+ #
110
+ # require 'fastimage'
111
+ #
112
+ # FastImage.type("http://stephensykes.com/images/ss.com_x.gif")
113
+ # => :gif
114
+ # FastImage.type("http://stephensykes.com/images/pngimage")
115
+ # => :png
116
+ # FastImage.type("http://farm4.static.flickr.com/3023/3047236863_9dce98b836.jpg")
117
+ # => :jpeg
118
+ # FastImage.type("http://www-ece.rice.edu/~wakin/images/lena512.bmp")
119
+ # => :bmp
120
+ # FastImage.type("test/fixtures/test.jpg")
121
+ # => :jpeg
122
+ # FastImage.type("http://pennysmalls.com/does_not_exist")
123
+ # => nil
124
+ #
125
+ # === Supported options
126
+ # [:timeout]
127
+ # Overrides the default timeout of 2 seconds. Applies both to reading from and opening the http connection.
128
+ # [:raise_on_failure]
129
+ # If set to true causes an exception to be raised if the image type cannot be found for any reason.
130
+ #
131
+ def self.type(uri, options={})
132
+ new(uri, options.merge(:type_only=>true)).type
133
+ end
134
+
135
+ def initialize(uri, options={})
136
+ @property = options[:type_only] ? :type : :size
137
+ @timeout = options[:timeout] || DefaultTimeout
138
+ @uri = uri
139
+ begin
140
+ @parsed_uri = URI.parse(uri)
141
+ rescue URI::InvalidURIError
142
+ fetch_using_open_uri
143
+ else
144
+ if @parsed_uri.scheme == "http" || @parsed_uri.scheme == "https"
145
+ fetch_using_http
146
+ else
147
+ fetch_using_open_uri
148
+ end
149
+ end
150
+ raise SizeNotFound if options[:raise_on_failure] && @property == :size && !@size
151
+ rescue Timeout::Error, SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ECONNRESET,
152
+ ImageFetchFailure, Net::HTTPBadResponse, EOFError, Errno::ENOENT
153
+ raise ImageFetchFailure if options[:raise_on_failure]
154
+ rescue NoMethodError # 1.8.7p248 can raise this due to a net/http bug
155
+ raise ImageFetchFailure if options[:raise_on_failure]
156
+ rescue UnknownImageType
157
+ raise UnknownImageType if options[:raise_on_failure]
158
+ end
159
+
160
+ private
161
+
162
+ def fetch_using_http
163
+ setup_http
164
+ @http.request_get(@parsed_uri.request_uri) do |res|
165
+ raise ImageFetchFailure unless res.is_a?(Net::HTTPSuccess)
166
+ res.read_body do |str|
167
+ break if parse_packet(str)
168
+ end
169
+ end
170
+ end
171
+
172
+ def setup_http
173
+ @http = Net::HTTP.new(@parsed_uri.host, @parsed_uri.port)
174
+ @http.use_ssl = (@parsed_uri.scheme == "https")
175
+ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
176
+ @http.open_timeout = @timeout
177
+ @http.read_timeout = @timeout
178
+ end
179
+
180
+ def fetch_using_open_uri
181
+ open(@uri) do |s|
182
+ while str = s.read(LocalFileChunkSize)
183
+ break if parse_packet(str)
184
+ end
185
+ end
186
+ end
187
+
188
+ # returns true once result is achieved
189
+ #
190
+ def parse_packet(str)
191
+ @str = (@unused_str || "") + str
192
+ @strpos = 0
193
+ begin
194
+ result = send("parse_#{@property}")
195
+ if result
196
+ instance_variable_set("@#{@property}", result)
197
+ true
198
+ end
199
+ rescue MoreCharsNeeded
200
+ false
201
+ end
202
+ end
203
+
204
+ def parse_size
205
+ @type = parse_type unless @type
206
+ @strpos = 0
207
+ send("parse_size_for_#{@type}")
208
+ end
209
+
210
+ def get_chars(n)
211
+ if @strpos + n - 1 >= @str.size
212
+ @unused_str = @str[@strpos..-1]
213
+ raise MoreCharsNeeded
214
+ else
215
+ result = @str[@strpos..(@strpos + n - 1)]
216
+ @strpos += n
217
+ result
218
+ end
219
+ end
220
+
221
+ def get_byte
222
+ get_chars(1).unpack("C")[0]
223
+ end
224
+
225
+ def read_int(str)
226
+ size_bytes = str.unpack("CC")
227
+ (size_bytes[0] << 8) + size_bytes[1]
228
+ end
229
+
230
+ def parse_type
231
+ case get_chars(2)
232
+ when "BM"
233
+ :bmp
234
+ when "GI"
235
+ :gif
236
+ when 0xff.chr + 0xd8.chr
237
+ :jpeg
238
+ when 0x89.chr + "P"
239
+ :png
240
+ else
241
+ raise UnknownImageType
242
+ end
243
+ end
244
+
245
+ def parse_size_for_gif
246
+ get_chars(11)[6..10].unpack('SS')
247
+ end
248
+
249
+ def parse_size_for_png
250
+ get_chars(25)[16..24].unpack('NN')
251
+ end
252
+
253
+ def parse_size_for_jpeg
254
+ loop do
255
+ @state = case @state
256
+ when nil
257
+ get_chars(2)
258
+ :started
259
+ when :started
260
+ get_byte == 0xFF ? :sof : :started
261
+ when :sof
262
+ c = get_byte
263
+ if (0xe0..0xef).include?(c)
264
+ :skipframe
265
+ elsif [0xC0..0xC3, 0xC5..0xC7, 0xC9..0xCB, 0xCD..0xCF].detect {|r| r.include? c}
266
+ :readsize
267
+ else
268
+ :skipframe
269
+ end
270
+ when :skipframe
271
+ @skip_chars = read_int(get_chars(2)) - 2
272
+ :do_skip
273
+ when :do_skip
274
+ get_chars(@skip_chars)
275
+ :started
276
+ when :readsize
277
+ s = get_chars(7)
278
+ return [read_int(s[5..6]), read_int(s[3..4])]
279
+ end
280
+ end
281
+ end
282
+
283
+ def parse_size_for_bmp
284
+ d = get_chars(29)[14..28]
285
+ d.unpack("C")[0] == 40 ? d[4..-1].unpack('LL') : d[4..8].unpack('SS')
286
+ end
287
+ end
@@ -0,0 +1,5 @@
1
+ module Middleman
2
+ module ClownCar
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1 @@
1
+ require "middleman-clowncar"
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "middleman-clowncar/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "middleman-clowncar"
7
+ s.version = Middleman::ClownCar::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Thomas Reynolds"]
10
+ s.email = ["me@tdreyno.com"]
11
+ s.homepage = "https://github.com/middleman/middleman-clowncar"
12
+ s.summary = %q{Adds ClownCar to Middleman}
13
+ s.description = %q{Adds ClownCar to Middleman}
14
+
15
+ s.rubyforge_project = "middleman-clowncar"
16
+
17
+ s.files = `git ls-files -z`.split("\0")
18
+ s.test_files = `git ls-files -z -- {fixtures,features}/*`.split("\0")
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_dependency("middleman-core", [">= 3.1.5"])
22
+ end
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: middleman-clowncar
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Thomas Reynolds
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-11-03 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.1.5
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 3.1.5
27
+ description: Adds ClownCar to Middleman
28
+ email:
29
+ - me@tdreyno.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - .gitignore
35
+ - .travis.yml
36
+ - Gemfile
37
+ - LICENSE.md
38
+ - README.md
39
+ - Rakefile
40
+ - features/clowncar_tag_build.feature
41
+ - features/clowncar_tag_preview.feature
42
+ - features/generate_clowncar_build.feature
43
+ - features/generate_clowncar_preview.feature
44
+ - features/step_definitions/server_steps.rb
45
+ - features/support/env.rb
46
+ - fixtures/clowncar-app/config.rb
47
+ - fixtures/clowncar-app/source/images/logo-with-fallback/big.png
48
+ - fixtures/clowncar-app/source/images/logo-with-fallback/fallback.png
49
+ - fixtures/clowncar-app/source/images/logo-with-fallback/medium.png
50
+ - fixtures/clowncar-app/source/images/logo-with-fallback/small.png
51
+ - fixtures/clowncar-app/source/images/logo/big.png
52
+ - fixtures/clowncar-app/source/images/logo/fallback.png
53
+ - fixtures/clowncar-app/source/images/logo/medium.png
54
+ - fixtures/clowncar-app/source/images/logo/small.png
55
+ - fixtures/clowncar-app/source/index.html.erb
56
+ - lib/middleman-clowncar.rb
57
+ - lib/middleman-clowncar/extension.rb
58
+ - lib/middleman-clowncar/fastimage.rb
59
+ - lib/middleman-clowncar/version.rb
60
+ - lib/middleman_extension.rb
61
+ - middleman-clowncar.gemspec
62
+ homepage: https://github.com/middleman/middleman-clowncar
63
+ licenses: []
64
+ metadata: {}
65
+ post_install_message:
66
+ rdoc_options: []
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ requirements: []
80
+ rubyforge_project: middleman-clowncar
81
+ rubygems_version: 2.0.3
82
+ signing_key:
83
+ specification_version: 4
84
+ summary: Adds ClownCar to Middleman
85
+ test_files:
86
+ - features/clowncar_tag_build.feature
87
+ - features/clowncar_tag_preview.feature
88
+ - features/generate_clowncar_build.feature
89
+ - features/generate_clowncar_preview.feature
90
+ - features/step_definitions/server_steps.rb
91
+ - features/support/env.rb
92
+ - fixtures/clowncar-app/config.rb
93
+ - fixtures/clowncar-app/source/images/logo-with-fallback/big.png
94
+ - fixtures/clowncar-app/source/images/logo-with-fallback/fallback.png
95
+ - fixtures/clowncar-app/source/images/logo-with-fallback/medium.png
96
+ - fixtures/clowncar-app/source/images/logo-with-fallback/small.png
97
+ - fixtures/clowncar-app/source/images/logo/big.png
98
+ - fixtures/clowncar-app/source/images/logo/fallback.png
99
+ - fixtures/clowncar-app/source/images/logo/medium.png
100
+ - fixtures/clowncar-app/source/images/logo/small.png
101
+ - fixtures/clowncar-app/source/index.html.erb
102
+ has_rdoc: