rack-tidy 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,87 @@
1
+ = Tidy Markup Cleaner for Rack
2
+
3
+ Rack::Tidy cleans text/html markup by automatically
4
+ indenting and reformatting content. Best results are achieved
5
+ with valid markup, when you simply want to use this component
6
+ to produce clean (X)HTML rendered by templating systems such as ERb.
7
+
8
+ Rack::Tidy relies on the power of the Tidy gem and defaults to settings
9
+ based on convention. However, you can override these through configuration.
10
+
11
+ For more information about the Rack specification, check out
12
+
13
+ http://rack.rubyforge.org/
14
+
15
+ == Installation
16
+
17
+ Prerequisites:
18
+
19
+ -Rack gem (sudo gem install rack)
20
+ -Tidy gem (sudo gem install tidy)
21
+
22
+ From Gem:
23
+
24
+ $ sudo gem install webficient-rack-tidy
25
+
26
+ With a local working copy:
27
+
28
+ $ git clone git://github.com/webficient/rack-tidy.git
29
+ $ rake build && sudo rake install
30
+
31
+ == Usage
32
+
33
+ Basic Usage
34
+ -----------
35
+
36
+ Rack::Tidy is implemented as a piece of Rack middleware and can be used with
37
+ any Rack-based application. If your application includes a rackup (`.ru`) file
38
+ or uses Rack::Builder to construct the application pipeline, simply require
39
+ and use as follows:
40
+
41
+ require 'rack/tidy'
42
+
43
+ use Rack::Tidy
44
+ run app
45
+
46
+ Using with Rails
47
+ ----------------
48
+
49
+ Add this to your `config/environment.rb`:
50
+
51
+ # above Rails::Initializer block
52
+ require 'rack/tidy'
53
+
54
+ # inside Rails::Initializer block
55
+ config.middleware.use Rack::Tidy
56
+
57
+ You should now see `Rack::Cache` listed in the middleware pipeline:
58
+
59
+ rake middleware
60
+
61
+ Configuration Options
62
+ ---------------------
63
+
64
+ The Tidy gem requires setting an internal path variable that points to the Tidy library,
65
+ which will differ per platform. Rack::Tidy defaults to '/usr/lib/libtidy.A.dylib'
66
+ which is the default location for the Tidy gem on Mac Leopard. To override the constant,
67
+ simply define it in your application's configuration file:
68
+
69
+ TIDY_LIB = '/usr/lib/tidylib.so'
70
+
71
+ Need Rack::Tidy to ignore certain paths? In your config, pass in an optional array of paths:
72
+
73
+ # Rails example
74
+ config.middleware.use Rack::Tidy,
75
+ :ignore_paths => ['/admin', '/cms']
76
+
77
+ Rack::Tidy relies on convention with regard to Tidy's configuration (see Rack::Tidy::Cleaner for details). If you want to override/set attributes supported by the Tidy gem, declare them in your configuration as an optional hash:
78
+
79
+ # Rails example
80
+ config.middleware.use Rack::Tidy,
81
+ 'indent-spaces' => 4
82
+
83
+ See http://tidy.sourceforge.net/docs/quickref.html for Tidy gem config options
84
+
85
+ == Copyright
86
+
87
+ Copyright (c) 2009 Phil Misiowiec, Webficient LLC. See MIT-LICENSE for details.
@@ -0,0 +1,47 @@
1
+ require 'rack'
2
+
3
+ # = Tidy Markup Cleaner for Rack
4
+ #
5
+ # Rack::Tidy cleans text/html markup by automatically
6
+ # indenting and reformatting content. Best results are achieved
7
+ # with valid markup, when you simply want to use this component
8
+ # to produce clean (X)HTML rendered by templating systems such as ERb.
9
+ #
10
+ # Rack::Tidy relies on the power of the Tidy gem and defaults to settings
11
+ # based on convention. However, you can override these through configuration.
12
+ #
13
+ # === Usage
14
+ #
15
+ # Within a rackup file (or with Rack::Builder):
16
+ # require 'rack/tidy'
17
+ # use Rack::Tidy,
18
+ # :ignore_paths => ['/admin', '/cms'],
19
+ # 'indent-spaces' => 4
20
+ # run app
21
+ #
22
+ # Rails example:
23
+ # # above Rails::Initializer block
24
+ # require 'rack/tidy'
25
+ #
26
+ # # inside Rails::Initializer block
27
+ # config.middleware.use Rack::Tidy,
28
+ # :ignore_paths => ['/admin', '/cms'],
29
+ # 'indent-spaces' => 4
30
+ module Rack::Tidy
31
+ autoload :Cleaner, 'rack/tidy/cleaner'
32
+
33
+ # Specify path of Tidy library, e.g.
34
+ # "/usr/lib/libtidy.A.dylib" (Mac; also the default if not set)
35
+ # "/usr/lib/tidylib.so" (Ubuntu)
36
+ # "/usr/lib/libtidy-0.99.so.0" (Fedora/CentOS)
37
+ TIDY_LIB = defined?(::TIDY_LIB) ? ::TIDY_LIB : '/usr/lib/libtidy.A.dylib'
38
+
39
+ # Create a new Rack::Tidy middleware component that cleans text/html markup
40
+ # using the Tidy gem. The +options+ Hash can be used to specify which paths
41
+ # should be ignored during processing as well as Tidy gem configuration values.
42
+ # See Cleaner for defaults and http://tidy.sourceforge.net/docs/quickref.html
43
+ # for more options
44
+ def self.new(backend, options = {})
45
+ Cleaner.new(backend, options)
46
+ end
47
+ end
@@ -0,0 +1,63 @@
1
+ require 'tidy'
2
+
3
+ module Rack::Tidy
4
+ # This class is the interface between Rack and the Tidy gem
5
+ class Cleaner
6
+
7
+ # Defaults for the Tidy gem config
8
+ DEFAULT_TIDY_OPTS = {
9
+ 'char-encoding' => 'utf8',
10
+ 'indent' => true,
11
+ 'indent-spaces' => 2,
12
+ 'tidy-mark' => false,
13
+ 'wrap' => 0 }
14
+
15
+ # Tidy gem options, see http://tidy.sourceforge.net/docs/quickref.html
16
+ attr_accessor :tidy_options
17
+
18
+ # Paths to be ignored during Rack::Tidy processing
19
+ attr_accessor :ignore_paths
20
+
21
+ def initialize(app, options = {})
22
+ ::Tidy.path = TIDY_LIB
23
+ @app = app
24
+ self.ignore_paths = options[:ignore_paths] || []
25
+ self.tidy_options = DEFAULT_TIDY_OPTS.merge(options)
26
+ end
27
+
28
+ # method required by Rack interface
29
+ def call(env)
30
+ call! env
31
+ end
32
+
33
+ # thread safe version using shallow copy of env
34
+ def call!(env)
35
+ @env = env.dup
36
+ status, @headers, response = @app.call(@env)
37
+ if should_clean?
38
+ @headers.delete('Content-Length')
39
+ response = Rack::Response.new(
40
+ tidy_markup(response.respond_to?(:body) ? response.body : response),
41
+ status,
42
+ @headers
43
+ )
44
+ response.finish
45
+ response.to_a
46
+ else
47
+ [status, @headers, response]
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def should_clean? #:nodoc:
54
+ @headers["Content-Type"] &&
55
+ @headers["Content-Type"].include?("text/html") &&
56
+ self.ignore_paths.none? { |p| @env["PATH_INFO"].start_with?(p) }
57
+ end
58
+
59
+ def tidy_markup(content) #:nodoc:
60
+ ::Tidy.open(self.tidy_options) { |tidy| tidy.clean(content) }
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,97 @@
1
+ module RackTidySampleData
2
+
3
+ DIRTY_HTML = <<-dirty
4
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
5
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
6
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
7
+ <head>
8
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
9
+ <title>True Blood - Wikipedia, the free encyclopedia</title>
10
+ <link href="/stylesheets/style.css" media="screen" rel="stylesheet" type="text/css" />
11
+ </head>
12
+ <body>
13
+ <p><i><b>True Blood</b></i> is an <a href="/wiki/Television_in_the_United_States" title="Television in the United States">American</a> <a href="/wiki/Television_drama_series" title="Television drama series" class="mw-redirect">television drama series</a> created and produced by <a href="/wiki/Alan_Ball_(screenwriter)" title="Alan Ball (screenwriter)">Alan Ball</a>. It is based on the <i><a href="/wiki/The_Southern_Vampire_Mysteries" title="The Southern Vampire Mysteries">The Southern Vampire Mysteries</a></i> series of novels by <a href="/wiki/Charlaine_Harris" title="Charlaine Harris">Charlaine Harris</a>. The show is broadcast on the premium cable network <a href="/wiki/HBO" title="HBO">HBO</a> in the United States. It is produced by HBO in association with Ball's production company, Your Face Goes Here Entertainment. It premiered on September 7, 2008.</p>
14
+ <h1>Episode Guide</h1>
15
+ <ul>
16
+ <li><a href="/wiki/True_Blood_(season_1)">Season One</a></li>
17
+ <li><a href="/wiki/True_Blood_(season_2)">Season Two</a></li>
18
+ </ul>
19
+ </body>
20
+ </html>
21
+ dirty
22
+
23
+ CLEAN_HTML = <<-clean
24
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
25
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
26
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
27
+ <head>
28
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
29
+ <title>
30
+ True Blood - Wikipedia, the free encyclopedia
31
+ </title>
32
+ <link href="/stylesheets/style.css" media="screen" rel="stylesheet" type="text/css" />
33
+ </head>
34
+ <body>
35
+ <p>
36
+ <i><b>True Blood</b></i> is an <a href="/wiki/Television_in_the_United_States" title="Television in the United States">American</a> <a href="/wiki/Television_drama_series" title="Television drama series" class="mw-redirect">television drama series</a> created and produced by <a href="/wiki/Alan_Ball_(screenwriter)" title="Alan Ball (screenwriter)">Alan Ball</a>. It is based on the <i><a href="/wiki/The_Southern_Vampire_Mysteries" title="The Southern Vampire Mysteries">The Southern Vampire Mysteries</a></i> series of novels by <a href="/wiki/Charlaine_Harris" title="Charlaine Harris">Charlaine Harris</a>. The show is broadcast on the premium cable network <a href="/wiki/HBO" title="HBO">HBO</a> in the United States. It is produced by HBO in association with Ball's production company, Your Face Goes Here Entertainment. It premiered on September 7, 2008.
37
+ </p>
38
+ <h1>
39
+ Episode Guide
40
+ </h1>
41
+ <ul>
42
+ <li>
43
+ <a href="/wiki/True_Blood_(season_1)">Season One</a>
44
+ </li>
45
+ <li>
46
+ <a href="/wiki/True_Blood_(season_2)">Season Two</a>
47
+ </li>
48
+ </ul>
49
+ </body>
50
+ </html>
51
+ clean
52
+
53
+ CLEAN_HTML_WITH_4_SPACE_INDENTS = <<-clean_with_4
54
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
55
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
56
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
57
+ <head>
58
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
59
+ <title>
60
+ True Blood - Wikipedia, the free encyclopedia
61
+ </title>
62
+ <link href="/stylesheets/style.css" media="screen" rel="stylesheet" type="text/css" />
63
+ </head>
64
+ <body>
65
+ <p>
66
+ <i><b>True Blood</b></i> is an <a href="/wiki/Television_in_the_United_States" title="Television in the United States">American</a> <a href="/wiki/Television_drama_series" title="Television drama series" class="mw-redirect">television drama series</a> created and produced by <a href="/wiki/Alan_Ball_(screenwriter)" title="Alan Ball (screenwriter)">Alan Ball</a>. It is based on the <i><a href="/wiki/The_Southern_Vampire_Mysteries" title="The Southern Vampire Mysteries">The Southern Vampire Mysteries</a></i> series of novels by <a href="/wiki/Charlaine_Harris" title="Charlaine Harris">Charlaine Harris</a>. The show is broadcast on the premium cable network <a href="/wiki/HBO" title="HBO">HBO</a> in the United States. It is produced by HBO in association with Ball's production company, Your Face Goes Here Entertainment. It premiered on September 7, 2008.
67
+ </p>
68
+ <h1>
69
+ Episode Guide
70
+ </h1>
71
+ <ul>
72
+ <li>
73
+ <a href="/wiki/True_Blood_(season_1)">Season One</a>
74
+ </li>
75
+ <li>
76
+ <a href="/wiki/True_Blood_(season_2)">Season Two</a>
77
+ </li>
78
+ </ul>
79
+ </body>
80
+ </html>
81
+ clean_with_4
82
+
83
+ CSS = <<-css
84
+ body {
85
+ font-family: "Lucida Grande", "Lucida Sans Unicode", Verdana, sans-serif;
86
+ font-size: 1em;
87
+ margin: 0 auto;
88
+ }
89
+ css
90
+
91
+ JS = <<-js
92
+ function(foo) {
93
+ alert('bar')
94
+ }
95
+ js
96
+
97
+ end
@@ -0,0 +1,103 @@
1
+ require 'test_helper'
2
+ require 'rack_tidy_sample_data'
3
+
4
+ class RackTidyTest < Test::Unit::TestCase
5
+ include RackTidySampleData
6
+
7
+ def get_response(path, body, content_type = 'text/html', options = {})
8
+ app = Rack::Builder.new do
9
+ use Rack::Tidy, options
10
+ run lambda { |env| [200, {'Content-Type' => content_type}, [body] ] }
11
+ end
12
+ Rack::MockRequest.new(app).get(path)
13
+ end
14
+
15
+ context "Rack::Tidy" do
16
+ context "with content type equal to 'text/html'" do
17
+ setup do
18
+ @response = get_response('/', DIRTY_HTML)
19
+ end
20
+ should "clean response body" do
21
+ assert_equal CLEAN_HTML, @response.body
22
+ end
23
+
24
+ context "with ignore paths containing one item that matches current path" do
25
+ setup do
26
+ @response = get_response('/cms', DIRTY_HTML, 'text/html', :ignore_paths => '/cms')
27
+ end
28
+ should "not clean response body" do
29
+ assert_equal DIRTY_HTML, @response.body
30
+ end
31
+ end
32
+
33
+ context "with ignore paths containing array of items with one matching current path" do
34
+ setup do
35
+ @response = get_response('/cms',
36
+ DIRTY_HTML,
37
+ 'text/html',
38
+ :ignore_paths => ['/admin', '/cms'])
39
+ end
40
+ should "not clean response body" do
41
+ assert_equal DIRTY_HTML, @response.body
42
+ end
43
+ end
44
+
45
+ context "with ignore paths containing array of items that don't match current path" do
46
+ setup do
47
+ @response = get_response('/',
48
+ DIRTY_HTML,
49
+ 'text/html',
50
+ :ignore_paths => ['/admin', '/cms'])
51
+ end
52
+ should "clean response body" do
53
+ assert_equal CLEAN_HTML, @response.body
54
+ end
55
+ end
56
+
57
+ context "with 'indent-spaces' set to 4" do
58
+ setup do
59
+ @response = get_response('/',
60
+ DIRTY_HTML,
61
+ 'text/html',
62
+ 'indent-spaces' => 4)
63
+ end
64
+
65
+ should "clean response body, indenting with 4 spaces" do
66
+ assert_equal CLEAN_HTML_WITH_4_SPACE_INDENTS, @response.body
67
+ end
68
+ end
69
+ end
70
+
71
+ context "with content type equal to 'text/css'" do
72
+ setup do
73
+ @response = get_response('/', CSS, 'text/css')
74
+ end
75
+ should "not clean response body" do
76
+ assert_equal CSS, @response.body
77
+ end
78
+ end
79
+
80
+ context "with content type equal to 'application/javascript'" do
81
+ setup do
82
+ @response = get_response('/', JS, 'application/javascript')
83
+ end
84
+ should "not clean response body" do
85
+ assert_equal JS, @response.body
86
+ end
87
+ end
88
+
89
+ context "with ignore path set and multiple requests" do
90
+ setup do
91
+ app = Rack::Builder.new do
92
+ use Rack::Tidy, :ignore_paths => '/cms'
93
+ run lambda { |env| [200, {'Content-Type' => 'text/html'}, [DIRTY_HTML] ] }
94
+ end
95
+ Rack::MockRequest.new(app).get('/')
96
+ @response = Rack::MockRequest.new(app).get('/cms')
97
+ end
98
+ should "not clean response body" do
99
+ assert_equal DIRTY_HTML, @response.body
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,10 @@
1
+ $:.push File.join(File.dirname(__FILE__), '..', 'lib')
2
+
3
+ require 'rubygems'
4
+ require 'test/unit'
5
+ require 'shoulda'
6
+ require 'rack/tidy'
7
+ require 'rack/mock'
8
+
9
+ class Test::Unit::TestCase
10
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rack-tidy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Phil Misiowiec
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-19 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rake
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: tidy
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ description: Rack middleware for automatically cleaning markup using Tidy
36
+ email: phil@webficient.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - README.rdoc
43
+ files:
44
+ - lib/rack/tidy.rb
45
+ - lib/rack/tidy/cleaner.rb
46
+ - README.rdoc
47
+ has_rdoc: true
48
+ homepage: http://github.com/webficient/rack-tidy
49
+ post_install_message:
50
+ rdoc_options:
51
+ - --charset=UTF-8
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ version:
66
+ requirements: []
67
+
68
+ rubyforge_project:
69
+ rubygems_version: 1.3.1
70
+ signing_key:
71
+ specification_version: 2
72
+ summary: Rack middleware for automatically cleaning markup using Tidy
73
+ test_files:
74
+ - test/rack_tidy_sample_data.rb
75
+ - test/rack_tidy_test.rb
76
+ - test/test_helper.rb