rack-unscripted 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .DS_Store
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in rack-unscripted.gemspec
4
+ gemspec
@@ -0,0 +1,20 @@
1
+ Copyright 2011 Casey Dreier.
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,76 @@
1
+ = Rack::Unscripted
2
+
3
+ This is a small piece of Rack middleware that will append a message to your HTML warning a user that they need to enable JavaScript in order to properly view your site.
4
+
5
+ The Rack middleware will append a <tt><div></tt> right after the opening body tag, but hide it via a CSS directive that is written by JavaScript in the <tt><head></tt> section. This prevents any flashing that can happen by merely hiding the element via JS directly. We don't use the <tt><noscript></tt> tag since it has spotty support and doesn't work when a user is using a browser plugin to whitelist JS on certain sites.
6
+
7
+ The div that is created can be referenced in CSS the the id, <tt>rack-unscripted-no-javascript-warning</tt>, so you can style this warning (when it does get displayed) to your heart's content.
8
+
9
+ == Example
10
+
11
+ Original HTML:
12
+
13
+ <html>
14
+ <head>
15
+ <title>The Bucket of Truth</title>
16
+ </head>
17
+ <body>
18
+ ...stuff!...
19
+ </body>
20
+ </html>
21
+
22
+ HTML with Rack::Unscripted enabled:
23
+
24
+ <html>
25
+ <head>
26
+ <title>The Bucket of Truth</title>
27
+ <script type="text/javascript">
28
+ document.write('<style>.rack-unscripted-no-javascript-warning { display:none }</style>');
29
+ </script>
30
+ </head>
31
+ <body>
32
+ <div id='rack-unscripted-no-javascript-warning'>
33
+ Warning, this site requires JavaScript to function properly. Please enable it.
34
+ </div>
35
+ ...stuff!...
36
+ </body>
37
+ </html>
38
+
39
+ == Installation
40
+
41
+ Make sure to install this gem:
42
+
43
+ gem install rack-unscripted
44
+
45
+ or, add the following to your Gemfile:
46
+
47
+ gem 'rack-unscripted'
48
+
49
+ Then you need to configure your middleware stack to use this library.
50
+
51
+ == Usage
52
+
53
+ use Rack::Unscripted
54
+
55
+ or
56
+
57
+ use Rack::Unscripted, "Custom warning message to users without JavaScript enabled."
58
+
59
+ == Example Configuration
60
+
61
+ === Rails 3.x
62
+
63
+ In config/initializers/rack_unscripted.rb
64
+
65
+ MyApplicationName::Application.config.middleware use "Rack::Unscripted"
66
+
67
+ === Rails 2.3.x
68
+
69
+ In config/environment.rb
70
+
71
+ config.middleware.use "Rack::Unscripted"
72
+
73
+ === Sinatra
74
+
75
+ require 'rack/unscripted'
76
+ use Rack::Unscripted
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1 @@
1
+ require 'rack/unscripted'
@@ -0,0 +1,78 @@
1
+ module Rack
2
+ class Unscripted
3
+ def initialize(app, warning_message = nil)
4
+ self.warning_message = warning_message if warning_message
5
+ @app = app
6
+ end
7
+
8
+ def call(env)
9
+ @status, @headers, @response = @app.call(env)
10
+ if valid_content_type?(@headers['Content-Type']) && valid_status?(@status)
11
+ @response.each do |response_line|
12
+ insert_js(response_line) if response_line =~ head_regex
13
+ insert_html(response_line) if response_line =~ body_regex
14
+ end
15
+ end
16
+ [@status, @headers, @response]
17
+ end
18
+
19
+ private
20
+
21
+ attr_writer :warning_message
22
+
23
+ def insert_js(response_line)
24
+ add_to_content_length(inline_code.length)
25
+ response_line.sub!(head_regex, inline_code + '\1')
26
+ end
27
+
28
+ # Inserts HTML of javascript warning after the opening body tag.
29
+ def insert_html(response_line)
30
+ add_to_content_length(no_javascript_warning.length)
31
+ response_line.sub!(body_regex, '\1'+ no_javascript_warning)
32
+ end
33
+
34
+ def no_javascript_warning
35
+ "<div id='rack-unscripted-no-javascript-warning'>#{warning_message}</div>"
36
+ end
37
+
38
+ def inline_code
39
+ <<-END
40
+ <script type="text/javascript">document.write('<style>#rack-unscripted-no-javascript-warning{display:none;}</style>');</script>
41
+ END
42
+ end
43
+
44
+ # Regular Expression to find the opening body tag.
45
+ def body_regex
46
+ /(<\s*body[^>]*>)/i
47
+ end
48
+
49
+ # Regular expression to find the closing </head> tag in a document.
50
+ def head_regex
51
+ /(<\s*\/head[^>]*>)/i
52
+ end
53
+
54
+ # Appends the given number to the current content length in the headers.
55
+ def add_to_content_length(number)
56
+ if @headers['Content-Length']
57
+ @headers['Content-Length'] = (@headers['Content-Length'].to_i + number.to_i).to_s
58
+ end
59
+ end
60
+
61
+ # Returns +true+ if the content type is text/html. No need to add this message
62
+ # to any other types of content.
63
+ def valid_content_type?(content_type)
64
+ content_type.respond_to?(:include?) && content_type.include?("text/html")
65
+ end
66
+
67
+ # Returns +true+ if the HTTP response code is such that we should append this warning message.
68
+ def valid_status?(response_code)
69
+ [200, 404].include? response_code.to_i
70
+ end
71
+
72
+ # Attribute reader for the warning message. Sets a default value.
73
+ def warning_message
74
+ @warning_message ||= 'Warning, this site requires javascript to function properly. Please enable it.'
75
+ end
76
+
77
+ end
78
+ end
@@ -0,0 +1,5 @@
1
+ module Rack
2
+ class Unscripted
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,40 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # $:.push File.expand_path("lib", __FILE__)
3
+ require File.expand_path('../lib/version.rb', __FILE__)
4
+ Gem::Specification.new do |s|
5
+ s.name = "rack-unscripted"
6
+ s.version = Rack::Unscripted::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ["Casey Dreier"]
9
+ s.email = ["casey.dreier@gmail.com"]
10
+ s.homepage = "https://github.com/daphonz/rack-unscripted"
11
+ s.summary = %q{Rack middleware to add a textual warning to your site for users who have Javascript disabled.}
12
+ s.description = %q{Many sites these days absolutely require a user to have Javascript enabled in order to function properly. You may have one yourself. Users that either have JS disabled or only allow trusted sites to execute JS should be given a textual warning that their user experience may be hampered.
13
+
14
+ This Rack middleware will append a div with a customizable message to the HTTP response body, right after the opening <body> tag. This warning message is then hidden via a CSS command that is written by Javascript.
15
+ }
16
+
17
+ s.rubyforge_project = "rack-unscripted"
18
+ s.extra_rdoc_files = ['README.rdoc']
19
+ s.license = 'MIT'
20
+ s.files = `git ls-files`.split("\n")
21
+ s.test_files = `git ls-files -- {test}/*`.split("\n")
22
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
23
+ s.require_paths = ["lib"]
24
+
25
+ s.add_development_dependency('rack-test')
26
+
27
+ if s.respond_to? :specification_version then
28
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
29
+ s.specification_version = 3
30
+
31
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
32
+ s.add_runtime_dependency(%q<rack>, [">= 1.0"])
33
+ else
34
+ s.add_dependency(%q<rack>, [">= 1.0"])
35
+ end
36
+ else
37
+ s.add_dependency(%q<rack>, [">= 1.0"])
38
+ end
39
+
40
+ end
@@ -0,0 +1,69 @@
1
+ require 'rubygems'
2
+ require 'rack/test'
3
+ require 'test/unit'
4
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/rack/unscripted')
5
+
6
+ class Rack::UnscriptedTest < Test::Unit::TestCase
7
+ include Rack::Test::Methods
8
+
9
+ def app
10
+ @other_app ||= other_app
11
+ @custom_warning_message ||= nil
12
+ Rack::Unscripted.new(@other_app, @custom_warning_message)
13
+ end
14
+
15
+ def test_inline_js_added
16
+ get '/'
17
+ assert last_response.body.include?(app.send(:inline_code) + '</head>')
18
+ end
19
+
20
+ def test_default_warning_message_added_to_response_body
21
+ get '/'
22
+ assert last_response.body.include?("<body class=\"such-and-such\">" + app.send(:no_javascript_warning))
23
+ end
24
+
25
+ def test_custom_message_added_to_response_body
26
+ @custom_warning_message = "¡Se necissita activar JavaScript!"
27
+ get '/'
28
+ assert last_response.body.include?(@custom_warning_message)
29
+ end
30
+
31
+ def test_content_length_is_increased
32
+ get '/'
33
+ expected = app.send(:inline_code).length + app.send(:no_javascript_warning).length + test_page_html.length
34
+ assert_equal expected, last_response.headers['Content-Length'].to_i
35
+ end
36
+
37
+ def test_takes_no_action_on_non_html_content_type
38
+ json = "{\"success\":\"success\"}"
39
+ @other_app = other_app(200, {'Content-Type' => 'application/json', 'Content-Length' => json.length.to_s}, Rack::Response.new(json))
40
+ get '/'
41
+ assert_equal json.length, last_response.headers['Content-Length'].to_i
42
+ assert_equal json, last_response.body
43
+ end
44
+
45
+ def test_takes_no_action_on_non_200_or_404_status_responses
46
+ # Obviously, this isn't all possible responses, but you get the idea.
47
+ [204, 302, 406, 500].each do |status|
48
+ @other_app = other_app(status)
49
+ get '/'
50
+ assert_equal test_page_html.length, last_response.headers['Content-Length'].to_i
51
+ assert_equal test_page_html, last_response.body
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ def other_app(status = 200, headers = nil, response = nil)
58
+ headers = {'Content-Type' => 'text/html', 'Content-Length' => test_page_html.length.to_s} unless headers
59
+ response = Rack::Response.new(test_page_html) unless response
60
+ Proc.new do |env|
61
+ [status, headers, response]
62
+ end
63
+ end
64
+
65
+ def test_page_html
66
+ '<html><head></head><body class="such-and-such"><p>The Bucket of Truth</p></body></html>'
67
+ end
68
+
69
+ end
metadata ADDED
@@ -0,0 +1,109 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rack-unscripted
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Casey Dreier
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-05-07 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rack-test
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :development
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: rack
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 15
44
+ segments:
45
+ - 1
46
+ - 0
47
+ version: "1.0"
48
+ type: :runtime
49
+ version_requirements: *id002
50
+ description: |
51
+ Many sites these days absolutely require a user to have Javascript enabled in order to function properly. You may have one yourself. Users that either have JS disabled or only allow trusted sites to execute JS should be given a textual warning that their user experience may be hampered.
52
+
53
+ This Rack middleware will append a div with a customizable message to the HTTP response body, right after the opening <body> tag. This warning message is then hidden via a CSS command that is written by Javascript.
54
+
55
+ email:
56
+ - casey.dreier@gmail.com
57
+ executables: []
58
+
59
+ extensions: []
60
+
61
+ extra_rdoc_files:
62
+ - README.rdoc
63
+ files:
64
+ - .gitignore
65
+ - Gemfile
66
+ - MIT-LICENSE
67
+ - README.rdoc
68
+ - Rakefile
69
+ - lib/rack-unscripted.rb
70
+ - lib/rack/unscripted.rb
71
+ - lib/version.rb
72
+ - rack-unscripted.gemspec
73
+ - test/unscripted_test.rb
74
+ has_rdoc: true
75
+ homepage: https://github.com/daphonz/rack-unscripted
76
+ licenses:
77
+ - MIT
78
+ post_install_message:
79
+ rdoc_options: []
80
+
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ hash: 3
89
+ segments:
90
+ - 0
91
+ version: "0"
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ hash: 3
98
+ segments:
99
+ - 0
100
+ version: "0"
101
+ requirements: []
102
+
103
+ rubyforge_project: rack-unscripted
104
+ rubygems_version: 1.6.2
105
+ signing_key:
106
+ specification_version: 3
107
+ summary: Rack middleware to add a textual warning to your site for users who have Javascript disabled.
108
+ test_files: []
109
+