undies 2.1.0 → 2.2.0

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.
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)