rack-modernizr 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.
@@ -0,0 +1,3 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in modernizr.gemspec
4
+ gemspec
@@ -0,0 +1,21 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rack-modernizr (0.0.1)
5
+ rack
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ rack (1.2.1)
11
+ test-spec (0.10.0)
12
+ test-unit (2.1.1)
13
+
14
+ PLATFORMS
15
+ ruby
16
+
17
+ DEPENDENCIES
18
+ rack
19
+ rack-modernizr!
20
+ test-spec (>= 0.9.0)
21
+ test-unit
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2010 Marshall C Yount; http://yountlabs.com
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 NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,27 @@
1
+ # rack-modernizr
2
+
3
+ [Modernizr](http://modernizr.com) is a javascript utility that interrogates a user's web browser to determine its capabilities. Unfortunately, all this delicious data is only available client-side.
4
+
5
+ rack-modernizr is a Rack Middleware that includes the Modernizr javascript and stuffs Modernizr's output into a cookie on the first page request.
6
+
7
+ Include it in your config.ru like so:
8
+
9
+ # This file is used by Rack-based servers to start the application.
10
+
11
+ require ::File.expand_path('../config/environment', __FILE__)
12
+ require 'modernizr'
13
+ use Rack::Modernizr
14
+
15
+ run MyApp::Application
16
+
17
+ or environment.rb
18
+
19
+ # Load the rails application
20
+ require File.expand_path('../application', __FILE__)
21
+
22
+ config.middleware.use Rack::Modernizr
23
+
24
+ # Initialize the rails application
25
+ MyApp::Application.initialize!
26
+
27
+ rack-modernizr was inspired by [jamesgpearce](https://github.com/jamesgpearce)'s super awesome [modernizr-server](https://github.com/jamesgpearce/modernizr-server). Some javascript was used from that project.
@@ -0,0 +1,26 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require "net/https"
5
+ require "uri"
6
+
7
+ require 'rake/rdoctask'
8
+ require 'rake/testtask'
9
+
10
+ desc "Run all the tests"
11
+ task :default => [:test]
12
+
13
+ desc "Run specs with test/unit style output"
14
+ task :test do
15
+ sh "specrb -Ilib:test -w #{ENV['TEST'] || '-a'} #{ENV['TESTOPTS']}"
16
+ end
17
+
18
+ desc "Run specs with specdoc style output"
19
+ task :spec do
20
+ sh "specrb -Ilib:test -s -w #{ENV['TEST'] || '-a'} #{ENV['TESTOPTS']}"
21
+ end
22
+
23
+ desc "Run all the tests"
24
+ task :fulltest do
25
+ sh "specrb -Ilib:test -w #{ENV['TEST'] || '-a'} #{ENV['TESTOPTS']}"
26
+ end
@@ -0,0 +1,72 @@
1
+ require 'rack'
2
+
3
+ module Rack
4
+ class Modernizr
5
+ include Rack::Utils
6
+
7
+ def initialize(app, options = {})
8
+ @app, @options = app, options
9
+ @options[:modernizr_js_url] ||= "http://cachedcommons.org/cache/modernizr/1.5.0/javascripts/modernizr-min.js"
10
+ @options[:cookie_name] ||= "Modernizr"
11
+ end
12
+
13
+ def call(env)
14
+ @req = Rack::Request.new(env)
15
+ status, headers, response = @app.call(env)
16
+
17
+ if should_add_modernizr?(status, headers, response)
18
+ response = add_modernizr(response)
19
+ fix_content_length(headers, response)
20
+ end
21
+
22
+ [status, headers, response]
23
+ end
24
+
25
+ def should_add_modernizr?(status, headers, response)
26
+ !@req.cookies.has_key?( @options[:cookie_name] ) &&
27
+ status==200 &&
28
+ headers["Content-Type"] &&
29
+ headers["Content-Type"].include?("text/html")
30
+ end
31
+
32
+ def fix_content_length(headers, response)
33
+ # Set new Content-Length, if it was set before we mutated the response body
34
+ if headers['Content-Length']
35
+ length = response.to_ary.inject(0) { |len, part| len + bytesize(part) }
36
+ headers['Content-Length'] = length.to_s
37
+ end
38
+ end
39
+
40
+ def add_modernizr(response, body = "")
41
+ response.each{ |s| body << s.to_s }
42
+ [body.gsub(/\<\/body\>/, "#{modernizr_js}</body>")]
43
+ end
44
+
45
+ def modernizr_js
46
+ "<script src=\"#{@options[:modernizr_js_url]}\" type=\"text/javascript\"></script>" +
47
+ "<script type=\"text/javascript\">#{set_cookie_js}</script>"
48
+ end
49
+
50
+ def set_cookie_js
51
+ "var m=Modernizr,c='';" +
52
+ "for(var f in m){" +
53
+ "if(f[0]=='_'){continue;}" +
54
+ "var t=typeof m[f];" +
55
+ "if(t=='function'){continue;}" +
56
+ "c+=(c?'|':'#{@options[:cookie_name]}=')+f+':';" +
57
+ "if(t=='object'){" +
58
+ "for(var s in m[f]){" +
59
+ "c+='/'+s+':'+(m[f][s]?'1':'0');" +
60
+ "}" +
61
+ "}else{" +
62
+ "c+=m[f]?'1':'0';" +
63
+ "}" +
64
+ "}" +
65
+ "c+=';path=/';" +
66
+ "try{" +
67
+ "document.cookie=c;" +
68
+ "}catch(e){}" +
69
+ ""
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,3 @@
1
+ module Modernizr
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "rack-modernizr/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "rack-modernizr"
7
+ s.version = Modernizr::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Marshall Yount"]
10
+ s.email = ["marshall@yountlabs.com"]
11
+ s.homepage = "http://rubygems.org/gems/rack-modernizr"
12
+ s.summary = %q{a Rack middleware that brings the power of the Modernizr javascript framework server-side}
13
+ s.description = %q{Rack::Modernizr is a Rack middleware that automagically includes the Modernizr javascript framework and exposes the results to your server-side scripts.}
14
+
15
+ s.rubyforge_project = "rack-modernizr"
16
+
17
+ s.add_dependency 'rack'
18
+ s.add_development_dependency 'test-spec', '>= 0.9.0'
19
+ s.add_development_dependency 'test-unit'
20
+
21
+ s.files = `git ls-files`.split("\n")
22
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
23
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
24
+ s.require_paths = ["lib"]
25
+ end
@@ -0,0 +1,94 @@
1
+ require 'test/spec'
2
+ require 'rack/mock'
3
+ require 'rack-modernizr'
4
+
5
+ context "Rack::Modernizr" do
6
+
7
+ context "when a modernizr cookie has not been set" do
8
+ specify "should insert script tag" do
9
+ test_body = "<html><body>Hello World</body></html>"
10
+ app = lambda { |env| [200, {'Content-Type' => 'text/html'}, [test_body]] }
11
+ request = Rack::MockRequest.env_for("/test.html")
12
+ body = Rack::Modernizr.new(app).call(request).last
13
+ body[0].should.include? "script"
14
+ end
15
+
16
+ specify "should correct Content-Length header" do
17
+ test_body = "<html><body>Hello World</body></html>"
18
+ app = lambda { |env| [200, {'Content-Type' => 'text/html', 'Content-Length' => 37}, [test_body]] }
19
+ request = Rack::MockRequest.env_for("/test.html")
20
+ status, headers, body = Rack::Modernizr.new(app).call(request)
21
+
22
+ body[0].length.should.not.equal test_body.length
23
+ body[0].length.should.equal body[0].length
24
+ end
25
+
26
+ specify "should insert code when charset is specified" do
27
+ test_body = "<html><body>Hello World</body></html>"
28
+ app = lambda { |env| [200, {'Content-Type' => 'text/html; charset=utf-8'}, [test_body]] }
29
+ request = Rack::MockRequest.env_for("/test.html")
30
+ body = Rack::Modernizr.new(app).call(request).last
31
+ body[0].should.include? "script"
32
+ end
33
+
34
+ specify "should insert correct URL if initialized" do
35
+ test_body = "<html><body>Hello World</body></html>"
36
+ app = lambda { |env| [200, {'Content-Type' => 'text/html; charset=utf-8'}, [test_body]] }
37
+ request = Rack::MockRequest.env_for("/test.html")
38
+ body = Rack::Modernizr.new(app, :modernizr_js_url => "http://distinctive.domain.com/modernizr.js").call(request).last
39
+ body[0].should.include? "distinctive.domain.com"
40
+ end
41
+
42
+ specify "should use cookie name if initialized" do
43
+ test_body = "<html><body>Hello World</body></html>"
44
+ app = lambda { |env| [200, {'Content-Type' => 'text/html; charset=utf-8'}, [test_body]] }
45
+ request = Rack::MockRequest.env_for("/test.html")
46
+ body = Rack::Modernizr.new(app, :cookie_name => "distinctive_name").call(request).last
47
+ body[0].should.include? "distinctive_name"
48
+ end
49
+
50
+ specify "should work if request body is fragmented" do
51
+ test_body = ["<html><body>Hello World</bo", "dy></html>"]
52
+ app = lambda { |env| [200, {'Content-Type' => 'text/html; charset=utf-8'}, test_body] }
53
+ request = Rack::MockRequest.env_for("/test.html")
54
+ body = Rack::Modernizr.new(app).call(request).last
55
+ body[0].should.include? "script"
56
+ end
57
+
58
+ specify "should not insert code if error response" do
59
+ test_body = "<html><body>Not Found!</body></html>"
60
+ app = lambda { |env| [404, {'Content-Type' => 'text/html'}, [test_body]] }
61
+ request = Rack::MockRequest.env_for("/test.html")
62
+ body = Rack::Modernizr.new(app).call(request).last
63
+ body[0].should.not.include? "script"
64
+ end
65
+
66
+ specify "should not insert code if non-html response" do
67
+ test_body = "<html><body>Silly invalid html document that somehow gets stamped to text/css</body></html>"
68
+ app = lambda { |env| [200, {'Content-Type' => 'text/css'}, [test_body]] }
69
+ request = Rack::MockRequest.env_for("/test.css")
70
+ body = Rack::Modernizr.new(app).call(request).last
71
+ body[0].should.not.include? "script"
72
+ end
73
+
74
+ specify "should not insert code if there is no body tag" do
75
+ test_body = "<html>Malformed document</html>"
76
+ app = lambda { |env| [200, {'Content-Type' => 'text/html'}, [test_body]] }
77
+ request = Rack::MockRequest.env_for("/test.html")
78
+ body = Rack::Modernizr.new(app).call(request).last
79
+ body[0].should.not.include? "script"
80
+ end
81
+ end
82
+
83
+
84
+ context "when a modernizr cookie has already been set" do
85
+ specify "should not mess with the response in any way" do
86
+ test_body = "<html><body>Hello World</body></html>"
87
+ app = lambda { |env| [200, {'Content-Type' => 'text/html'}, [test_body]] }
88
+ request = Rack::MockRequest.env_for("/test.html", "HTTP_COOKIE" => "Modernizr=blarghfasel")
89
+ body = Rack::Modernizr.new(app).call(request).last
90
+ puts body[0]
91
+ body[0].should.not.include? "script"
92
+ end
93
+ end
94
+ end
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rack-modernizr
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Marshall Yount
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-11-08 00:00:00 -06:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rack
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: test-spec
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ - 9
44
+ - 0
45
+ version: 0.9.0
46
+ type: :development
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: test-unit
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ segments:
57
+ - 0
58
+ version: "0"
59
+ type: :development
60
+ version_requirements: *id003
61
+ description: Rack::Modernizr is a Rack middleware that automagically includes the Modernizr javascript framework and exposes the results to your server-side scripts.
62
+ email:
63
+ - marshall@yountlabs.com
64
+ executables: []
65
+
66
+ extensions: []
67
+
68
+ extra_rdoc_files: []
69
+
70
+ files:
71
+ - .gitignore
72
+ - Gemfile
73
+ - Gemfile.lock
74
+ - LICENSE
75
+ - README.md
76
+ - Rakefile
77
+ - lib/rack-modernizr.rb
78
+ - lib/rack-modernizr/version.rb
79
+ - modernizr.gemspec
80
+ - test/spec_rack_modernizr.rb
81
+ has_rdoc: true
82
+ homepage: http://rubygems.org/gems/rack-modernizr
83
+ licenses: []
84
+
85
+ post_install_message:
86
+ rdoc_options: []
87
+
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ segments:
96
+ - 0
97
+ version: "0"
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ none: false
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ segments:
104
+ - 0
105
+ version: "0"
106
+ requirements: []
107
+
108
+ rubyforge_project: rack-modernizr
109
+ rubygems_version: 1.3.7
110
+ signing_key:
111
+ specification_version: 3
112
+ summary: a Rack middleware that brings the power of the Modernizr javascript framework server-side
113
+ test_files:
114
+ - test/spec_rack_modernizr.rb