rack-mason 0.1.2

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.
Files changed (72) hide show
  1. data/.gitignore +4 -0
  2. data/CHANGELOG +24 -0
  3. data/Gemfile +16 -0
  4. data/LICENSE +21 -0
  5. data/README.rdoc +54 -0
  6. data/Rakefile +23 -0
  7. data/examples/middlewares/initial.rb +27 -0
  8. data/examples/middlewares/intro.rb +16 -0
  9. data/examples/middlewares/l337.rb +21 -0
  10. data/examples/middlewares/stylizer.rb +15 -0
  11. data/examples/rackapp/app.rb +105 -0
  12. data/examples/rackapp/config.ru +16 -0
  13. data/examples/railsapp/README +243 -0
  14. data/examples/railsapp/Rakefile +10 -0
  15. data/examples/railsapp/app/controllers/application_controller.rb +10 -0
  16. data/examples/railsapp/app/controllers/tommy_boy_controller.rb +9 -0
  17. data/examples/railsapp/app/helpers/application_helper.rb +3 -0
  18. data/examples/railsapp/app/helpers/tommy_boy_helper.rb +2 -0
  19. data/examples/railsapp/app/views/layouts/application.html.erb +13 -0
  20. data/examples/railsapp/app/views/tommy_boy/index.html.erb +44 -0
  21. data/examples/railsapp/app/views/tommy_boy/more.html.erb +12 -0
  22. data/examples/railsapp/config/boot.rb +110 -0
  23. data/examples/railsapp/config/database.yml +22 -0
  24. data/examples/railsapp/config/environment.rb +50 -0
  25. data/examples/railsapp/config/environments/development.rb +17 -0
  26. data/examples/railsapp/config/environments/production.rb +28 -0
  27. data/examples/railsapp/config/environments/test.rb +28 -0
  28. data/examples/railsapp/config/initializers/backtrace_silencers.rb +7 -0
  29. data/examples/railsapp/config/initializers/inflections.rb +10 -0
  30. data/examples/railsapp/config/initializers/mime_types.rb +5 -0
  31. data/examples/railsapp/config/initializers/new_rails_defaults.rb +21 -0
  32. data/examples/railsapp/config/initializers/session_store.rb +15 -0
  33. data/examples/railsapp/config/locales/en.yml +5 -0
  34. data/examples/railsapp/config/routes.rb +4 -0
  35. data/examples/railsapp/db/development.sqlite3 +0 -0
  36. data/examples/railsapp/db/seeds.rb +7 -0
  37. data/examples/railsapp/doc/README_FOR_APP +2 -0
  38. data/examples/railsapp/public/404.html +30 -0
  39. data/examples/railsapp/public/422.html +30 -0
  40. data/examples/railsapp/public/500.html +30 -0
  41. data/examples/railsapp/public/favicon.ico +0 -0
  42. data/examples/railsapp/public/images/rails.png +0 -0
  43. data/examples/railsapp/public/javascripts/application.js +2 -0
  44. data/examples/railsapp/public/javascripts/controls.js +963 -0
  45. data/examples/railsapp/public/javascripts/dragdrop.js +973 -0
  46. data/examples/railsapp/public/javascripts/effects.js +1128 -0
  47. data/examples/railsapp/public/javascripts/prototype.js +4320 -0
  48. data/examples/railsapp/public/robots.txt +5 -0
  49. data/examples/railsapp/script/about +4 -0
  50. data/examples/railsapp/script/console +3 -0
  51. data/examples/railsapp/script/dbconsole +3 -0
  52. data/examples/railsapp/script/destroy +3 -0
  53. data/examples/railsapp/script/generate +3 -0
  54. data/examples/railsapp/script/performance/benchmarker +3 -0
  55. data/examples/railsapp/script/performance/profiler +3 -0
  56. data/examples/railsapp/script/plugin +3 -0
  57. data/examples/railsapp/script/runner +3 -0
  58. data/examples/railsapp/script/server +3 -0
  59. data/examples/railsapp/test/functional/tommy_boy_controller_test.rb +8 -0
  60. data/examples/railsapp/test/performance/browsing_test.rb +9 -0
  61. data/examples/railsapp/test/test_helper.rb +38 -0
  62. data/examples/railsapp/test/unit/helpers/tommy_boy_helper_test.rb +4 -0
  63. data/examples/sinatraapp/app.rb +107 -0
  64. data/gem.yml +17 -0
  65. data/lib/mason_helper.rb +76 -0
  66. data/lib/mason_test_helper.rb +99 -0
  67. data/lib/rack-mason.rb +70 -0
  68. data/test/rack-mason_test.rb +21 -0
  69. data/test/test_helper.rb +13 -0
  70. data/vex/gem.rake +36 -0
  71. data/vex/gem.rb +95 -0
  72. metadata +197 -0
@@ -0,0 +1,5 @@
1
+ # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
2
+ #
3
+ # To ban all spiders from the entire site uncomment the next two lines:
4
+ # User-Agent: *
5
+ # Disallow: /
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require File.expand_path('../../config/boot', __FILE__)
3
+ $LOAD_PATH.unshift "#{RAILTIES_PATH}/builtin/rails_info"
4
+ require 'commands/about'
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.expand_path('../../config/boot', __FILE__)
3
+ require 'commands/console'
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.expand_path('../../config/boot', __FILE__)
3
+ require 'commands/dbconsole'
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.expand_path('../../config/boot', __FILE__)
3
+ require 'commands/destroy'
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.expand_path('../../config/boot', __FILE__)
3
+ require 'commands/generate'
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.expand_path('../../../config/boot', __FILE__)
3
+ require 'commands/performance/benchmarker'
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.expand_path('../../../config/boot', __FILE__)
3
+ require 'commands/performance/profiler'
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.expand_path('../../config/boot', __FILE__)
3
+ require 'commands/plugin'
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.expand_path('../../config/boot', __FILE__)
3
+ require 'commands/runner'
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.expand_path('../../config/boot', __FILE__)
3
+ require 'commands/server'
@@ -0,0 +1,8 @@
1
+ require 'test_helper'
2
+
3
+ class TommyBoyControllerTest < ActionController::TestCase
4
+ # Replace this with your real tests.
5
+ test "the truth" do
6
+ assert true
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ require 'test_helper'
2
+ require 'performance_test_help'
3
+
4
+ # Profiling results for each test method are written to tmp/performance.
5
+ class BrowsingTest < ActionController::PerformanceTest
6
+ def test_homepage
7
+ get '/'
8
+ end
9
+ end
@@ -0,0 +1,38 @@
1
+ ENV["RAILS_ENV"] = "test"
2
+ require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
3
+ require 'test_help'
4
+
5
+ class ActiveSupport::TestCase
6
+ # Transactional fixtures accelerate your tests by wrapping each test method
7
+ # in a transaction that's rolled back on completion. This ensures that the
8
+ # test database remains unchanged so your fixtures don't have to be reloaded
9
+ # between every test method. Fewer database queries means faster tests.
10
+ #
11
+ # Read Mike Clark's excellent walkthrough at
12
+ # http://clarkware.com/cgi/blosxom/2005/10/24#Rails10FastTesting
13
+ #
14
+ # Every Active Record database supports transactions except MyISAM tables
15
+ # in MySQL. Turn off transactional fixtures in this case; however, if you
16
+ # don't care one way or the other, switching from MyISAM to InnoDB tables
17
+ # is recommended.
18
+ #
19
+ # The only drawback to using transactional fixtures is when you actually
20
+ # need to test transactions. Since your test is bracketed by a transaction,
21
+ # any transactions started in your code will be automatically rolled back.
22
+ self.use_transactional_fixtures = true
23
+
24
+ # Instantiated fixtures are slow, but give you @david where otherwise you
25
+ # would need people(:david). If you don't want to migrate your existing
26
+ # test cases which use the @david style and don't mind the speed hit (each
27
+ # instantiated fixtures translates to a database query per test method),
28
+ # then set this back to true.
29
+ self.use_instantiated_fixtures = false
30
+
31
+ # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
32
+ #
33
+ # Note: You'll currently still have to declare fixtures explicitly in integration tests
34
+ # -- they do not yet inherit this setting
35
+ fixtures :all
36
+
37
+ # Add more helper methods to be used by all tests here...
38
+ end
@@ -0,0 +1,4 @@
1
+ require 'test_helper'
2
+
3
+ class TommyBoyHelperTest < ActionView::TestCase
4
+ end
@@ -0,0 +1,107 @@
1
+ require 'rubygems'
2
+ require 'sinatra'
3
+ require File.join(File.dirname(__FILE__), '..', 'middlewares', 'initial')
4
+ require File.join(File.dirname(__FILE__), '..', 'middlewares', 'intro')
5
+ require File.join(File.dirname(__FILE__), '..', 'middlewares', 'l337')
6
+ require File.join(File.dirname(__FILE__), '..', 'middlewares', 'stylizer')
7
+
8
+ # Note that these middlewares will seem to be applied in backwards order.
9
+ # In other words, Rack::Stylizer parses the resulting HTML first, then
10
+ # passes it to Rack::Initial, then to Rack::L337, and finally to Rack::Intro.
11
+
12
+ 1.times do
13
+ use Rack::Intro
14
+ use Rack::L337
15
+ use Rack::Initial
16
+ use Rack::Stylizer
17
+ end
18
+
19
+ get '/' do
20
+ %Q{
21
+ <!DOCTYPE html
22
+ PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
23
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
24
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
25
+ <head>
26
+ <title>The Greatest Movie of All Time</title>
27
+ </head>
28
+ <body>
29
+ <div id="container">
30
+ <p>
31
+ What my associate is trying to say is that our new brake pads are really cool.
32
+ You're not even gonna believe it.
33
+ </p>
34
+ <p>
35
+ Like, um, let's say you're driving along
36
+ the road, with your family.<br />
37
+ And you're driving along...la de da...woo...<br />
38
+ And then all of a sudden
39
+ there's a truck tire
40
+ in the middle of the road
41
+ and you hit the brakes.<br />
42
+ Screeeee!
43
+ </p>
44
+ <p>
45
+ Woah, that was close.
46
+ </p>
47
+ <p>
48
+ Now let's see what happens when you're
49
+ driving with "the other guy's brake pads".
50
+ </p>
51
+ <p>
52
+ You're driving along,<br />
53
+ you're driving along,<br />
54
+ and all of a sudden your kids are
55
+ yelling from the back seat:<br />
56
+ "I gotta go to the bathroom, daddy!"<br />
57
+ "Not now, dammit!"<br />
58
+ "Truck tire! I can't stop! Aaaaa! Help!"<br />
59
+ "There's a cliff! Aaaaa!"<br />
60
+ And your family screaming:<br />
61
+ "Oh my God, we're burning alive!"<br />
62
+ "No! I can't feel my legs!"<br />
63
+ Here comes the meat-wagon! Woo woo woo!<br />
64
+ And the medic gets out and says:<br />
65
+ "Oh! My! God!"<br />
66
+ New guy's in the corner puking his guts out:<br />
67
+ Blllleeeeeeeaaaaaaaaaaah!<br />
68
+ Blllleeeeeeeaaaaaaaaaaah!<br />
69
+ </p>
70
+ <p>
71
+ All because you wanna save a coupla extra pennies.
72
+ </p>
73
+ <a href="/more">&laquo; inflict me with more &raquo;</a>
74
+ </div>
75
+ </body>
76
+ </html>
77
+ }
78
+ end
79
+
80
+ get '/more' do
81
+ %Q{
82
+ <!DOCTYPE html
83
+ PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
84
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
85
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
86
+ <head>
87
+ <title>More of the Greatest Movie of All Time</title>
88
+ </head>
89
+ <body>
90
+ <div id="container">
91
+ <p>
92
+ D+? Oh my God! I passed! I passed! Oh, man i got a D+! I'm gonna graduate!
93
+ I'm gonna graduate! D+!
94
+ </p>
95
+ <p>
96
+ Hey guys, do i look different now that i'm a college grad?
97
+ </p>
98
+ <p>
99
+ Apparently they give a lot fewer D+'s than D-'s.
100
+ It's not a grade they like to give out, i'll tell ya that right now.
101
+ </p>
102
+ <a href="/">&laquo; take me back &raquo;</a>
103
+ </div>
104
+ </body>
105
+ </html>
106
+ }
107
+ end
data/gem.yml ADDED
@@ -0,0 +1,17 @@
1
+ name: "rack-mason"
2
+ version: "0.1.2"
3
+ summary: "Helps you write Rack middleware using Nokogiri."
4
+ description:
5
+ If you are creating Rack middleware that changes the HTML response, use
6
+ Rack::Mason to get a head start. Rack::Mason takes care of the
7
+ boilerplate Rack glue so that you can focus on simply changing the HTML.
8
+
9
+ Note: this is a fork from https://github.com/techiferous/rack-mason (c) techiferous@gmail.com
10
+ homepage: http://github.com/radiospiel/rack-mason
11
+ author: radiospiel
12
+ email: radiospiel@open-lab.org
13
+ dependencies:
14
+ - nokogiri
15
+ - rack
16
+ - diffy
17
+ - colored
@@ -0,0 +1,76 @@
1
+ class NokogiriString
2
+ attr :nokogiri
3
+
4
+ def initialize(nokogiri)
5
+ @nokogiri = nokogiri
6
+ end
7
+
8
+ # A NokogiriString is not really a String, but is good enought
9
+ # in the Rack context to act like one.
10
+ def kind_of?(what)
11
+ return true if what == String
12
+ super
13
+ end
14
+
15
+ def to_str
16
+ @to_str ||= @nokogiri.to_s
17
+ end
18
+
19
+ def bytesize
20
+ to_str.bytesize
21
+ end
22
+
23
+ def to_s
24
+ to_str
25
+ end
26
+ end
27
+
28
+ module Rack
29
+
30
+ # MasonHelper was created to separate Mason's implementation from Mason's
31
+ # interface.
32
+ #
33
+ # This class basically contains all of the Rack code that you'd have to write every
34
+ # time you wanted to write a new middleware that modifies the HTML response.
35
+ #
36
+ module MasonHelper #:nodoc:
37
+
38
+ # Rack::Mason provides a call method so that your middleware doesn't have to.
39
+ def call(env)
40
+ status, @headers, @body = @app.call(env)
41
+ if status == 200 && html?
42
+ @request = Rack::Request.new(env)
43
+ body_string = @body.length == 1 ? @body[0] : @body.join("")
44
+
45
+ doc = body_string.respond_to?(:nokogiri) ? body_string.nokogiri : Nokogiri::HTML(body_string)
46
+
47
+ if doc && update_body(doc) != false
48
+ update_response_body(NokogiriString.new(doc))
49
+ end
50
+ end
51
+
52
+ [status, @headers, @body]
53
+ end
54
+
55
+ private
56
+
57
+ def html?
58
+ @headers["Content-Type"].to_s.include?("text/html")
59
+ end
60
+
61
+ def update_response_body(body)
62
+ # If we're dealing with a Rails response, we don't want to throw the
63
+ # response object away, we just want to update the response string.
64
+ if @body.class.name == "ActionController::Response"
65
+ @body.body = body
66
+ else
67
+ @body = [body]
68
+ end
69
+
70
+ #
71
+ # The content lenght might have changed... but there is Rack::ContentLength to add
72
+ # it later on again.
73
+ @headers.delete 'Content-Length'
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,99 @@
1
+ require 'rack/mock'
2
+ require 'diffy'
3
+ require 'colored'
4
+
5
+ # Mix this module into Test::Unit::TestCase to have access to these
6
+ # test helpers when using Test::Unit.
7
+ #
8
+ # Here's an example of how you can use these helper methods:
9
+ #
10
+ # def test_basic_document
11
+ # before_html = %Q{
12
+ # <!DOCTYPE html
13
+ # PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
14
+ # "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
15
+ # <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
16
+ # <head>
17
+ # <title>Testing Rack::SexChange</title>
18
+ # </head>
19
+ # <body>
20
+ # Hi, Mom!
21
+ # </body>
22
+ # </html>
23
+ # }
24
+ # expected_html = %Q{
25
+ # <!DOCTYPE html
26
+ # PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
27
+ # "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
28
+ # <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
29
+ # <head>
30
+ # <title>Testing Rack::SexChange</title>
31
+ # </head>
32
+ # <body>
33
+ # Hi, Dad!
34
+ # </body>
35
+ # </html>
36
+ # }
37
+ # after_html = process_html(before_html, Rack::SexChange)
38
+ # assert_html_equal expected_html, after_html
39
+ # end
40
+ #
41
+ # And here's an example of how you'd mix these helper methods into
42
+ # Test::Unit::TestCase:
43
+ #
44
+ # require 'test/unit'
45
+ # require 'rubygems'
46
+ # require 'plastic_test_helper'
47
+ #
48
+ # module Test
49
+ # module Unit
50
+ # class TestCase
51
+ #
52
+ # include MasonTestHelper
53
+ #
54
+ # end
55
+ # end
56
+ # end
57
+ #
58
+ module MasonTestHelper
59
+
60
+ # This takes care of the "plumbing" involved in testing your middleware.
61
+ # All you have to provide is an input HTML string, the class of
62
+ # your middleware (not the name of your class or an object, but
63
+ # the class itself), and finally some optional options to use when
64
+ # instantiating your middleware class.
65
+ #
66
+ # This method will run the input HTML string through the middleware
67
+ # and return the resulting HTML string (the body of the middleware's response).
68
+ #
69
+ # Examples:
70
+ # resulting_html = process_html(input_html, Rack::Linkify)
71
+ # resulting_html = process_html(input_html, Rack::Linkify, :twitter => true)
72
+ #
73
+ def process_html(html, middleware_class, options={})
74
+ app = lambda { |env| [200, {'Content-Type' => 'text/html'}, [html]] }
75
+ app2 = middleware_class.new(app, options)
76
+ Rack::MockRequest.new(app2).get('/', :lint => true).body
77
+ end
78
+
79
+ # this convenience method makes it easy to test changes to HTML strings
80
+ #
81
+ def assert_html_equal(expected_html_string, actual_html_string)
82
+ # Nokogiri does not preserve the same whitespace between tags when
83
+ # it processes HTML. This means we can't do a simple string comparison.
84
+ # However, if we run both the expected HTML string and the actual HTML
85
+ # string through Nokogiri, then the whitespace will be changed in
86
+ # the same way and we can do a simple string comparison.
87
+ expected = Nokogiri::HTML(expected_html_string).to_html
88
+ actual = Nokogiri::HTML(actual_html_string).to_html
89
+ preamble = "\n"
90
+ preamble = "*****************************************************\n"
91
+ preamble << "* The actual HTML does not match the expected HTML. *\n"
92
+ preamble << "* The differences are highlighted below. *\n"
93
+ preamble << "*****************************************************\n"
94
+ message = preamble.magenta
95
+ message << Diffy::Diff.new(expected, actual).to_s(:color)
96
+ assert_block(message) { expected == actual }
97
+ end
98
+
99
+ end
data/lib/rack-mason.rb ADDED
@@ -0,0 +1,70 @@
1
+ require 'nokogiri'
2
+ require File.join(File.dirname(__FILE__), 'mason_helper')
3
+
4
+ module Rack
5
+
6
+ # If you are creating Rack middleware that changes the HTML response, inherit
7
+ # from Rack::Mason to get a head start. Rack::Mason takes care of the
8
+ # boilerplate Rack glue so that you can focus on simply changing the HTML.
9
+ #
10
+ # There are two ways you can change the HTML: as a Nokogiri document or as
11
+ # a string. Simply define one of the following methods:
12
+ #
13
+ # def update_body(doc)
14
+ # ... insert code that changes the doc ...
15
+ # doc
16
+ # end
17
+ #
18
+ # Rack::Mason also provides some convenience methods for interacting with
19
+ # Rack and Nokogiri.
20
+ #
21
+ class Mason
22
+ include MasonHelper
23
+
24
+ # Rack::Mason provides an initialize method so that your middleware
25
+ # doesn't have to.
26
+ #
27
+ def initialize(app, options = {}) #:nodoc:
28
+ @app = app
29
+ @options = options.freeze
30
+ end
31
+
32
+ private
33
+
34
+ # returns the current request as a Rack::Request object
35
+ #
36
+ def request #:doc:
37
+ @request
38
+ end
39
+
40
+ # returns the hash of options that were given to your middleware
41
+ #
42
+ def options #:doc:
43
+ @options
44
+ end
45
+
46
+ # a convenience method for adding a new HTML element as the first child
47
+ # of another HTML element
48
+ #
49
+ def add_first_child(parent, new_child) #:doc:
50
+ parent.children.first.add_previous_sibling(new_child)
51
+ end
52
+
53
+ # a convenience method for quickly creating a new HTML element
54
+ #
55
+ def create_node(doc, node_name, content=nil) #:doc:
56
+ node = Nokogiri::XML::Node.new(node_name, doc)
57
+ node.content = content if content
58
+ node
59
+ end
60
+
61
+ # Nokogiri's node.content=(text) method automatically HTML escapes the given text.
62
+ # This can cause problems. This method updates the text of an HTML element
63
+ # without escaping the text.
64
+ #
65
+ def update_text(node, new_text) #:doc:
66
+ node.send(:native_content=, new_text)
67
+ end
68
+
69
+ end
70
+ end