undies 2.1.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -5,3 +5,5 @@ gemspec
5
5
 
6
6
  gem 'rake', '~>0.9.2'
7
7
  gem 'ruby-prof'
8
+ gem 'erubis'
9
+ gem 'ansi'
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- undies (2.1.0)
4
+ undies (2.2.0)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
@@ -12,6 +12,7 @@ GEM
12
12
  assert-view (0.5.0)
13
13
  ansi (~> 1.3)
14
14
  undies (~> 2.0)
15
+ erubis (2.7.0)
15
16
  rake (0.9.2)
16
17
  ruby-prof (0.10.8)
17
18
 
@@ -19,8 +20,10 @@ PLATFORMS
19
20
  ruby
20
21
 
21
22
  DEPENDENCIES
23
+ ansi
22
24
  assert (~> 0.7.3)
23
25
  bundler (~> 1.0)
26
+ erubis
24
27
  rake (~> 0.9.2)
25
28
  ruby-prof
26
29
  undies!
data/Rakefile CHANGED
@@ -4,4 +4,26 @@ Assert::RakeTasks.for(:test)
4
4
  require 'bundler'
5
5
  Bundler::GemHelper.install_tasks
6
6
 
7
- task :default => :build
7
+ task :default => :run_all
8
+
9
+ desc "Run the profiler on the large bench template."
10
+ task :run_profiler do
11
+ require 'bench/profiler_runner'
12
+ UndiesProfilerRunner.new('large').print_flat(STDOUT, :min_percent => 3)
13
+ end
14
+
15
+ desc "Run the benchmark script."
16
+ task :run_bench do
17
+ require 'bench/bench_runner'
18
+ UndiesBenchRunner.new
19
+ end
20
+
21
+ desc "Run all the tests, then the profiler, then the bench."
22
+ task :run_all do
23
+ Rake::Task['test'].invoke
24
+ puts
25
+ Rake::Task['run_profiler'].invoke
26
+ puts
27
+ Rake::Task['run_bench'].invoke
28
+ end
29
+
data/bench/bench ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bench/bench_runner'
4
+
5
+ UndiesBenchRunner.new
@@ -0,0 +1,118 @@
1
+ require 'benchmark'
2
+ require 'stringio'
3
+ require 'ansi'
4
+
5
+ require 'undies'
6
+ require 'erb'
7
+ require 'erubis'
8
+
9
+ class BenchResults
10
+
11
+ attr_reader :user, :system, :total, :real
12
+ attr_accessor :name, :ext, :size, :out, :outstream
13
+
14
+ def initialize(name, ext, size)
15
+ @name = name.to_s
16
+ @ext = ext.to_s
17
+ @size = size.to_s
18
+ @user, @system, @total, @real = 0
19
+ @outstream = StringIO.new(@out = "")
20
+ end
21
+
22
+ def file
23
+ File.expand_path("bench/#{@size}.html#{@ext}")
24
+ end
25
+
26
+ def user=(value_in_secs); @user = value_in_secs.to_f * 1000; end
27
+ def system=(value_in_secs); @system = value_in_secs.to_f * 1000; end
28
+ def total=(value_in_secs); @total = value_in_secs.to_f * 1000; end
29
+ def real=(value_in_secs); @real = value_in_secs.to_f * 1000; end
30
+
31
+ def to_s(meas=:real, basis=nil)
32
+ "#{name_s} (#{size_s}): #{time_s(meas)} ms #{"(#{basis_s(meas, basis)})" if basis}"
33
+ end
34
+
35
+ protected
36
+
37
+ def measure(&block)
38
+ Benchmark.measure(&block).to_s.strip.gsub(/[^\s|0-9|\.]/, '').split(/\s+/).tap do |values|
39
+ self.user, self.system, self.total, self.real = values
40
+ end
41
+ end
42
+
43
+ def name_s; @name.ljust(6); end
44
+ def size_s; @size.to_s; end
45
+ def time_s(meas); self.send(meas).to_s.rjust(7); end
46
+
47
+ def basis_s(meas, time)
48
+ diff = (time - self.send(meas))
49
+ perc = ((diff / time) * 100).round
50
+ if diff >= 0
51
+ ANSI.green + "+#{diff} ms, +#{perc}%" + ANSI.reset
52
+ else
53
+ ANSI.red + "#{diff} ms, #{perc}%" + ANSI.reset
54
+ end
55
+ end
56
+
57
+ end
58
+
59
+ class UndiesResults < BenchResults
60
+
61
+ def initialize(size='large')
62
+ super(:undies, '.rb', size)
63
+ measure do
64
+ Undies::Template.new(
65
+ Undies::Source.new(self.file),
66
+ {},
67
+ Undies::Output.new(self.outstream, :pp => 2)
68
+ )
69
+ end
70
+ end
71
+
72
+ end
73
+
74
+ class ErbResults < BenchResults
75
+
76
+ def initialize(size='large')
77
+ super(:erb, '.erb', size)
78
+ measure do
79
+ self.out = ERB.new(File.read(self.file), 0, "%<>").result(binding)
80
+ end
81
+ end
82
+
83
+ end
84
+
85
+ class ErubisResults < BenchResults
86
+
87
+ def initialize(size='large')
88
+ super(:erubis, '.erb', size)
89
+ measure do
90
+ self.out = Erubis::Eruby.new(File.read(self.file)).result(binding)
91
+ end
92
+ end
93
+
94
+ end
95
+
96
+ class UndiesBenchRunner
97
+
98
+ SIZES = {
99
+ :small => "~20 nodes",
100
+ :large => "~2000 nodes",
101
+ :verylarge => "~20000 nodes"
102
+ }
103
+
104
+ def initialize
105
+ puts "Benchmark Results:"
106
+ puts
107
+ [:small, :large, :verylarge].each do |size|
108
+ puts "#{size.to_s.upcase} (#{SIZES[size]})"
109
+ puts '-'*(size.to_s.length+3+SIZES[size].length)
110
+ basis = UndiesResults.new(size)
111
+ puts basis.to_s(:real)
112
+ puts ErbResults.new(size).to_s(:real, basis.real)
113
+ puts ErubisResults.new(size).to_s(:real, basis.real)
114
+ puts
115
+ end
116
+ end
117
+
118
+ end
@@ -0,0 +1,19 @@
1
+ <html>
2
+ <head></head>
3
+ <body>
4
+ <% 100.times do %>
5
+ <% 5.times do %>
6
+ Yo
7
+ <% end %>
8
+ <% 5.times do %>
9
+ YoYo
10
+ <% end %>
11
+ <% 5.times do %>
12
+ <br />
13
+ <% end %>
14
+ <% 5.times do %>
15
+ <div>Hi</div>
16
+ <% end %>
17
+ <% end %>
18
+ </body>
19
+ </html>
data/bench/large.html.rb CHANGED
@@ -1,32 +1,19 @@
1
1
  _html {
2
2
  _head {}
3
3
  _body {
4
-
5
- 10.times do
6
- _ "Yo"
7
- _ "Yo"
8
- _ "Yo"
9
- _ "Yo"
10
- _ "Yo"
11
-
12
- __ "YoYo"
13
- __ "YoYo"
14
- __ "YoYo"
15
- __ "YoYo"
16
- __ "YoYo"
17
-
18
- _br
19
- _br
20
- _br
21
- _br
22
- _br
23
-
24
- _div { _ "Hi" }
25
- _div { _ "Hi" }
26
- _div { _ "Hi" }
27
- _div { _ "Hi" }
28
- _div { _ "Hi" }
4
+ 100.times do
5
+ 5.times do
6
+ _ "Yo"
7
+ end
8
+ 5.times do
9
+ __ "YoYo"
10
+ end
11
+ 5.times do
12
+ _br
13
+ end
14
+ 5.times do
15
+ _div { _ "Hi" }
16
+ end
29
17
  end
30
-
31
18
  }
32
19
  }
data/bench/profiler ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bench/profiler_runner'
4
+
5
+ runner = UndiesProfilerRunner.new(ARGV[0] || 'large')
6
+ runner.print_flat(STDOUT, :min_percent => 1)
@@ -0,0 +1,32 @@
1
+ require 'stringio'
2
+ require 'ruby-prof'
3
+ require 'undies'
4
+ require 'bench/procs'
5
+
6
+ class UndiesProfilerRunner
7
+
8
+ attr_reader :result
9
+
10
+ def initialize(size)
11
+ file = "bench/#{size || 'large'}.html.rb"
12
+ @source = Undies::Source.new(File.expand_path(file))
13
+ @data = {}
14
+ @output = Undies::Output.new(StringIO.new(@out = ""))
15
+
16
+ @result = RubyProf.profile do
17
+ 10.times do
18
+ Undies::Template.new(@source, @data, @output)
19
+ end
20
+ end
21
+
22
+ end
23
+
24
+ def print_flat(outstream, opts={})
25
+ RubyProf::FlatPrinter.new(@result).print(outstream, opts)
26
+ end
27
+
28
+ def print_graph(outstream, opts={})
29
+ RubyProf::GraphPrinter.new(@result).print(outstream, opts)
30
+ end
31
+
32
+ end
@@ -0,0 +1,19 @@
1
+ <html>
2
+ <head></head>
3
+ <body>
4
+ <% 1.times do %>
5
+ <% 5.times do %>
6
+ Yo
7
+ <% end %>
8
+ <% 5.times do %>
9
+ YoYo
10
+ <% end %>
11
+ <% 5.times do %>
12
+ <br />
13
+ <% end %>
14
+ <% 5.times do %>
15
+ <div>Hi</div>
16
+ <% end %>
17
+ <% end %>
18
+ </body>
19
+ </html>
data/bench/small.html.rb CHANGED
@@ -1,32 +1,19 @@
1
1
  _html {
2
2
  _head {}
3
3
  _body {
4
-
5
4
  1.times do
6
- _ "Yo"
7
- _ "Yo"
8
- _ "Yo"
9
- _ "Yo"
10
- _ "Yo"
11
-
12
- __ "YoYo"
13
- __ "YoYo"
14
- __ "YoYo"
15
- __ "YoYo"
16
- __ "YoYo"
17
-
18
- _br
19
- _br
20
- _br
21
- _br
22
- _br
23
-
24
- _div { _ "Hi" }
25
- _div { _ "Hi" }
26
- _div { _ "Hi" }
27
- _div { _ "Hi" }
28
- _div { _ "Hi" }
5
+ 5.times do
6
+ _ "Yo"
7
+ end
8
+ 5.times do
9
+ __ "YoYo"
10
+ end
11
+ 5.times do
12
+ _br
13
+ end
14
+ 5.times do
15
+ _div { _ "Hi" }
16
+ end
29
17
  end
30
-
31
18
  }
32
19
  }
@@ -0,0 +1,19 @@
1
+ <html>
2
+ <head></head>
3
+ <body>
4
+ <% 1000.times do %>
5
+ <% 5.times do %>
6
+ Yo
7
+ <% end %>
8
+ <% 5.times do %>
9
+ YoYo
10
+ <% end %>
11
+ <% 5.times do %>
12
+ <br />
13
+ <% end %>
14
+ <% 5.times do %>
15
+ <div>Hi</div>
16
+ <% end %>
17
+ <% end %>
18
+ </body>
19
+ </html>
@@ -1,32 +1,19 @@
1
1
  _html {
2
2
  _head {}
3
3
  _body {
4
-
5
4
  1000.times do
6
- _ "Yo"
7
- _ "Yo"
8
- _ "Yo"
9
- _ "Yo"
10
- _ "Yo"
11
-
12
- __ "YoYo"
13
- __ "YoYo"
14
- __ "YoYo"
15
- __ "YoYo"
16
- __ "YoYo"
17
-
18
- _br
19
- _br
20
- _br
21
- _br
22
- _br
23
-
24
- _div { _ "Hi" }
25
- _div { _ "Hi" }
26
- _div { _ "Hi" }
27
- _div { _ "Hi" }
28
- _div { _ "Hi" }
5
+ 5.times do
6
+ _ "Yo"
7
+ end
8
+ 5.times do
9
+ __ "YoYo"
10
+ end
11
+ 5.times do
12
+ _br
13
+ end
14
+ 5.times do
15
+ _div { _ "Hi" }
16
+ end
29
17
  end
30
-
31
18
  }
32
19
  }
@@ -16,11 +16,19 @@ module Undies
16
16
  html + if k_v.last.kind_of?(::Hash)
17
17
  hash_attrs(k_v.last, k_v.first)
18
18
  else
19
- " #{k_v.first}=\"#{k_v.last.gsub('"', '&quot;').gsub('<', '&lt;')}\""
19
+ " #{k_v.first}=\"#{escape_attr_value(k_v.last)}\""
20
20
  end
21
21
  end
22
22
  end
23
23
 
24
+ def self.escape_attr_value(value)
25
+ value.
26
+ to_s.
27
+ gsub('&', '&amp;').
28
+ gsub('<', '&lt;').
29
+ gsub('"', '&quot;')
30
+ end
31
+
24
32
  def self.content(element)
25
33
  nil
26
34
  end
@@ -19,6 +19,23 @@ module Undies
19
19
  template.instance_variable_get("@_undies_output").flush
20
20
  end
21
21
 
22
+ # Ripped from Rack v1.3.0 ======================================
23
+ # => ripped b/c I don't want a dependency on Rack for just this
24
+ ESCAPE_HTML = {
25
+ "&" => "&amp;",
26
+ "<" => "&lt;",
27
+ ">" => "&gt;",
28
+ "'" => "&#x27;",
29
+ '"' => "&quot;",
30
+ "/" => "&#x2F;"
31
+ }
32
+ ESCAPE_HTML_PATTERN = Regexp.union(*ESCAPE_HTML.keys)
33
+ # Escape ampersands, brackets and quotes to their HTML/XML entities.
34
+ def self.escape_html(string)
35
+ string.to_s.gsub(ESCAPE_HTML_PATTERN){|c| ESCAPE_HTML[c] }
36
+ end
37
+ # end Rip from Rack v1.3.0 =====================================
38
+
22
39
  def initialize(*args)
23
40
  output = if args.last.kind_of?(Output)
24
41
  args.pop
@@ -67,7 +84,7 @@ module Undies
67
84
  end
68
85
 
69
86
  # Add a text node (data escaped) to the nodes of the current node
70
- def _(data=""); self.__ self.escape_html(data.to_s); end
87
+ def _(data=""); self.__ self.class.escape_html(data.to_s); end
71
88
 
72
89
  # Add a text node with the data un-escaped
73
90
  def __(data=""); @_undies_output.node(Node.new(data.to_s)); end
@@ -99,22 +116,5 @@ module Undies
99
116
  end
100
117
  # ==============================================================
101
118
 
102
- # Ripped from Rack v1.3.0 ======================================
103
- # => ripped b/c I don't want a dependency on Rack for just this
104
- ESCAPE_HTML = {
105
- "&" => "&amp;",
106
- "<" => "&lt;",
107
- ">" => "&gt;",
108
- "'" => "&#x27;",
109
- '"' => "&quot;",
110
- "/" => "&#x2F;"
111
- }
112
- ESCAPE_HTML_PATTERN = Regexp.union(*ESCAPE_HTML.keys)
113
- # Escape ampersands, brackets and quotes to their HTML/XML entities.
114
- def escape_html(string)
115
- string.to_s.gsub(ESCAPE_HTML_PATTERN){|c| ESCAPE_HTML[c] }
116
- end
117
- # end Rip from Rack v1.3.0 =====================================
118
-
119
119
  end
120
120
  end
@@ -1,3 +1,3 @@
1
1
  module Undies
2
- VERSION = "2.1.0"
2
+ VERSION = "2.2.0"
3
3
  end
data/test/element_test.rb CHANGED
@@ -56,6 +56,11 @@ class Undies::Element
56
56
  assert_includes 'escaped="not &lt; escaped"', attrs
57
57
  end
58
58
 
59
+ should "escape '&' in attr values" do
60
+ attrs = Undies::Element.hash_attrs('escaped' => 'not & escaped')
61
+ assert_includes 'escaped="not &amp; escaped"', attrs
62
+ end
63
+
59
64
  should "convert a nested hash to element attrs" do
60
65
  attrs = Undies::Element.hash_attrs({
61
66
  :class => "testing", :id => "test_2",
@@ -16,9 +16,8 @@ class Undies::Template
16
16
  end
17
17
  subject { @t }
18
18
 
19
- should have_class_method :output, :flush
20
- should have_instance_method :to_s
21
- should have_instance_methods :element, :tag, :escape_html
19
+ should have_class_method :output, :flush, :escape_html
20
+ should have_instance_methods :to_s, :element, :tag
22
21
  should have_instance_methods :_, :__, :___
23
22
  should have_instance_methods :__yield, :__partial
24
23
 
@@ -88,7 +87,7 @@ class Undies::Template
88
87
  Undies::Template.new(Undies::Source.new do
89
88
  _ data
90
89
  end, {:data => @data}, @output)
91
- assert_equal subject.send(:escape_html, @data), @out
90
+ assert_equal subject.class.escape_html(@data), @out
92
91
  end
93
92
 
94
93
  should "add the text un-escaped using the '__' method" do
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: undies
3
3
  version: !ruby/object:Gem::Version
4
- hash: 11
4
+ hash: 7
5
5
  prerelease:
6
6
  segments:
7
7
  - 2
8
- - 1
8
+ - 2
9
9
  - 0
10
- version: 2.1.0
10
+ version: 2.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Kelly Redding
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-01-10 00:00:00 Z
18
+ date: 2012-02-02 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  type: :development
@@ -63,10 +63,16 @@ files:
63
63
  - Gemfile.lock
64
64
  - README.rdoc
65
65
  - Rakefile
66
+ - bench/bench
67
+ - bench/bench_runner.rb
68
+ - bench/large.html.erb
66
69
  - bench/large.html.rb
67
70
  - bench/procs.rb
68
- - bench/profiler.rb
71
+ - bench/profiler
72
+ - bench/profiler_runner.rb
73
+ - bench/small.html.erb
69
74
  - bench/small.html.rb
75
+ - bench/verylarge.html.erb
70
76
  - bench/verylarge.html.rb
71
77
  - lib/undies.rb
72
78
  - lib/undies/element.rb
data/bench/profiler.rb DELETED
@@ -1,25 +0,0 @@
1
- require 'ruby-prof'
2
- require 'undies'
3
- require 'bench/procs'
4
-
5
- file = "bench/#{ARGV[0] || 'large'}.html.rb"
6
- proc = eval("@#{ARGV[0] || 'large'}_proc")
7
- result = nil
8
-
9
- File.open('bench/output.txt', 'a+') do |outstream|
10
-
11
- output = Undies::Output.new(outstream, :pp => 2)
12
-
13
- result = RubyProf.profile do
14
- 50.times do
15
- Undies::Template.new(Undies::Source.new(File.expand_path(file)), {}, output)
16
- end
17
- 50.times do
18
- Undies::Template.new(Undies::Source.new(proc), {}, output)
19
- end
20
- end
21
-
22
- end
23
-
24
- printer = RubyProf::FlatPrinter.new(result).print(STDOUT, :min_percent => 1)
25
- # printer = RubyProf::GraphPrinter.new(result).print(STDOUT)