undies 1.2.0 → 2.0.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/.gitignore +2 -0
- data/Gemfile +2 -1
- data/Gemfile.lock +10 -5
- data/Rakefile +2 -4
- data/bench/large.html.rb +32 -0
- data/bench/procs.rb +106 -0
- data/bench/profiler.rb +25 -0
- data/bench/small.html.rb +32 -0
- data/bench/verylarge.html.rb +32 -0
- data/lib/undies/element.rb +61 -61
- data/lib/undies/named_source.rb +54 -0
- data/lib/undies/node.rb +16 -24
- data/lib/undies/node_buffer.rb +35 -0
- data/lib/undies/output.rb +64 -0
- data/lib/undies/source.rb +58 -12
- data/lib/undies/source_stack.rb +22 -0
- data/lib/undies/template.rb +47 -134
- data/lib/undies/version.rb +1 -1
- data/lib/undies.rb +1 -11
- data/test/element_test.rb +106 -99
- data/test/helper.rb +4 -2
- data/test/irb.rb +3 -4
- data/test/named_source_test.rb +91 -0
- data/test/node_buffer_test.rb +54 -0
- data/test/node_test.rb +19 -10
- data/test/output_test.rb +116 -0
- data/test/source_stack_test.rb +48 -0
- data/test/source_test.rb +131 -27
- data/test/template_test.rb +120 -145
- data/test/templates/layout.html.rb +1 -1
- data/undies.gemspec +1 -1
- metadata +27 -23
- data/lib/undies/element_stack.rb +0 -35
- data/lib/undies/node_list.rb +0 -35
- data/lib/undies/partial.rb +0 -23
- data/lib/undies/partial_data.rb +0 -32
- data/test/element_stack_test.rb +0 -77
- data/test/fixtures/partial_template.rb +0 -6
- data/test/node_list_test.rb +0 -69
- data/test/partial_data_test.rb +0 -100
- data/test/partial_test.rb +0 -63
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,21 +1,26 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
undies (
|
4
|
+
undies (2.0.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: http://rubygems.org/
|
8
8
|
specs:
|
9
|
-
|
9
|
+
ansi (1.4.1)
|
10
|
+
assert (0.7.3)
|
11
|
+
assert-view (~> 0.5)
|
12
|
+
assert-view (0.5.0)
|
13
|
+
ansi (~> 1.3)
|
14
|
+
undies (~> 2.0)
|
10
15
|
rake (0.9.2)
|
11
|
-
|
12
|
-
leftright (~> 0.9.0)
|
16
|
+
ruby-prof (0.10.8)
|
13
17
|
|
14
18
|
PLATFORMS
|
15
19
|
ruby
|
16
20
|
|
17
21
|
DEPENDENCIES
|
22
|
+
assert (~> 0.7.3)
|
18
23
|
bundler (~> 1.0)
|
19
24
|
rake (~> 0.9.2)
|
20
|
-
|
25
|
+
ruby-prof
|
21
26
|
undies!
|
data/Rakefile
CHANGED
data/bench/large.html.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
_html {
|
2
|
+
_head {}
|
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" }
|
29
|
+
end
|
30
|
+
|
31
|
+
}
|
32
|
+
}
|
data/bench/procs.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
@small_proc = Proc.new do
|
2
|
+
_html {
|
3
|
+
_head {}
|
4
|
+
_body {
|
5
|
+
|
6
|
+
1.times do
|
7
|
+
_ "Yo"
|
8
|
+
_ "Yo"
|
9
|
+
_ "Yo"
|
10
|
+
_ "Yo"
|
11
|
+
_ "Yo"
|
12
|
+
|
13
|
+
__ "YoYo"
|
14
|
+
__ "YoYo"
|
15
|
+
__ "YoYo"
|
16
|
+
__ "YoYo"
|
17
|
+
__ "YoYo"
|
18
|
+
|
19
|
+
_br
|
20
|
+
_br
|
21
|
+
_br
|
22
|
+
_br
|
23
|
+
_br
|
24
|
+
|
25
|
+
_div { _ "Hi" }
|
26
|
+
_div { _ "Hi" }
|
27
|
+
_div { _ "Hi" }
|
28
|
+
_div { _ "Hi" }
|
29
|
+
_div { _ "Hi" }
|
30
|
+
end
|
31
|
+
|
32
|
+
}
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
@large_proc = Proc.new do
|
38
|
+
_html {
|
39
|
+
_head {}
|
40
|
+
_body {
|
41
|
+
|
42
|
+
10.times do
|
43
|
+
_ "Yo"
|
44
|
+
_ "Yo"
|
45
|
+
_ "Yo"
|
46
|
+
_ "Yo"
|
47
|
+
_ "Yo"
|
48
|
+
|
49
|
+
__ "YoYo"
|
50
|
+
__ "YoYo"
|
51
|
+
__ "YoYo"
|
52
|
+
__ "YoYo"
|
53
|
+
__ "YoYo"
|
54
|
+
|
55
|
+
_br
|
56
|
+
_br
|
57
|
+
_br
|
58
|
+
_br
|
59
|
+
_br
|
60
|
+
|
61
|
+
_div { _ "Hi" }
|
62
|
+
_div { _ "Hi" }
|
63
|
+
_div { _ "Hi" }
|
64
|
+
_div { _ "Hi" }
|
65
|
+
_div { _ "Hi" }
|
66
|
+
end
|
67
|
+
|
68
|
+
}
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
@verylarge_proc = Proc.new do
|
74
|
+
_html {
|
75
|
+
_head {}
|
76
|
+
_body {
|
77
|
+
|
78
|
+
1000.times do
|
79
|
+
_ "Yo"
|
80
|
+
_ "Yo"
|
81
|
+
_ "Yo"
|
82
|
+
_ "Yo"
|
83
|
+
_ "Yo"
|
84
|
+
|
85
|
+
__ "YoYo"
|
86
|
+
__ "YoYo"
|
87
|
+
__ "YoYo"
|
88
|
+
__ "YoYo"
|
89
|
+
__ "YoYo"
|
90
|
+
|
91
|
+
_br
|
92
|
+
_br
|
93
|
+
_br
|
94
|
+
_br
|
95
|
+
_br
|
96
|
+
|
97
|
+
_div { _ "Hi" }
|
98
|
+
_div { _ "Hi" }
|
99
|
+
_div { _ "Hi" }
|
100
|
+
_div { _ "Hi" }
|
101
|
+
_div { _ "Hi" }
|
102
|
+
end
|
103
|
+
|
104
|
+
}
|
105
|
+
}
|
106
|
+
end
|
data/bench/profiler.rb
ADDED
@@ -0,0 +1,25 @@
|
|
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)
|
data/bench/small.html.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
_html {
|
2
|
+
_head {}
|
3
|
+
_body {
|
4
|
+
|
5
|
+
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" }
|
29
|
+
end
|
30
|
+
|
31
|
+
}
|
32
|
+
}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
_html {
|
2
|
+
_head {}
|
3
|
+
_body {
|
4
|
+
|
5
|
+
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" }
|
29
|
+
end
|
30
|
+
|
31
|
+
}
|
32
|
+
}
|
data/lib/undies/element.rb
CHANGED
@@ -1,34 +1,53 @@
|
|
1
1
|
require 'undies/node'
|
2
|
-
require 'undies/node_list'
|
3
|
-
require 'undies/element_stack'
|
4
2
|
|
5
3
|
module Undies
|
6
4
|
class Element < Node
|
7
5
|
|
8
|
-
|
9
|
-
|
6
|
+
# have as many methods to the class level as possilbe to keep from
|
7
|
+
# polluting the public instance methods and to maximize the effectiveness
|
8
|
+
# of the Element#method_missing logic
|
9
|
+
|
10
|
+
def self.html_attrs(attrs="", ns=nil)
|
11
|
+
if attrs.kind_of? ::Hash
|
12
|
+
attrs.empty? ? '' : (attrs.keys.map(&:to_s).sort.map(&:to_sym).inject('') do |html, key|
|
13
|
+
ak = ns ? "#{ns}_#{key}" : key.to_s
|
14
|
+
av = attrs[key]
|
15
|
+
html + (av.kind_of?(::Hash) ? html_attrs(av, ak) : " #{ak}=\"#{av}\"")
|
16
|
+
end)
|
17
|
+
else
|
18
|
+
attrs.to_s
|
19
|
+
end
|
20
|
+
end
|
10
21
|
|
11
|
-
def
|
12
|
-
|
13
|
-
|
22
|
+
def self.content(element)
|
23
|
+
nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.flush(output, element)
|
27
|
+
output.pp_use_indent = true
|
28
|
+
output << element.instance_variable_get("@start_tag")
|
29
|
+
if (cbs = element.instance_variable_get("@content_blocks")).size > 0
|
30
|
+
output.pp_level += 1
|
31
|
+
output.pp_use_indent = false
|
32
|
+
cbs.each{ |content| content.call }
|
33
|
+
output.flush
|
34
|
+
output.pp_level -= 1
|
14
35
|
end
|
36
|
+
output << element.instance_variable_get("@end_tag") if element.instance_variable_get("@end_tag")
|
37
|
+
output.pp_use_indent = true
|
38
|
+
end
|
39
|
+
|
40
|
+
def initialize(name, attrs={}, &block)
|
15
41
|
if !attrs.kind_of?(::Hash)
|
16
42
|
raise ArgumentError, "#{name.inspect} attrs must be provided as a Hash."
|
17
43
|
end
|
18
|
-
super(@___nodes = NodeList.new)
|
19
|
-
@stack = stack
|
20
|
-
@content_writes = 0
|
21
|
-
@___name = name.to_s
|
22
|
-
@___attrs = attrs
|
23
|
-
self.___content = block
|
24
|
-
end
|
25
|
-
|
26
|
-
def start_tag
|
27
|
-
"<#{@___name}#{html_attrs(@___attrs)}" + (@content_writes > 0 ? ">" : " />")
|
28
|
-
end
|
29
44
|
|
30
|
-
|
31
|
-
@
|
45
|
+
@name = name.to_s
|
46
|
+
@attrs = attrs
|
47
|
+
@content_blocks = []
|
48
|
+
@content_blocks << block if block
|
49
|
+
@start_tag = start_tag
|
50
|
+
@end_tag = end_tag
|
32
51
|
end
|
33
52
|
|
34
53
|
# CSS proxy methods ============================================
|
@@ -37,9 +56,13 @@ module Undies
|
|
37
56
|
|
38
57
|
def method_missing(meth, *args, &block)
|
39
58
|
if meth.to_s =~ ID_METH_REGEX
|
40
|
-
|
59
|
+
proxy($1, args.first || {}, block) do |value|
|
60
|
+
@attrs.merge!(:id => value)
|
61
|
+
end
|
41
62
|
elsif meth.to_s =~ CLASS_METH_REGEX
|
42
|
-
|
63
|
+
proxy($1, args.first || {}, block) do |value|
|
64
|
+
@attrs[:class] = [@attrs[:class], value].compact.join(' ')
|
65
|
+
end
|
43
66
|
else
|
44
67
|
super
|
45
68
|
end
|
@@ -55,59 +78,36 @@ module Undies
|
|
55
78
|
# ==============================================================
|
56
79
|
|
57
80
|
def ==(other)
|
58
|
-
other.
|
59
|
-
other.
|
60
|
-
other.
|
81
|
+
other.instance_variable_get("@name") == @name &&
|
82
|
+
other.instance_variable_get("@attrs") == @attrs &&
|
83
|
+
other.instance_variable_get("@nodes") == @nodes
|
61
84
|
end
|
62
85
|
|
86
|
+
# overriding this because the base Node class defines a 'to_s' method that
|
87
|
+
# needs to be honored
|
63
88
|
def to_str(*args)
|
64
89
|
"Undies::Element:#{self.object_id} " +
|
65
|
-
"@name=#{
|
90
|
+
"@name=#{@name.inspect}, @attrs=#{@attrs.inspect}, @nodes=#{@nodes.inspect}"
|
66
91
|
end
|
67
92
|
alias_method :inspect, :to_str
|
68
93
|
|
69
|
-
def to_ary(*args)
|
70
|
-
self.___nodes
|
71
|
-
end
|
72
|
-
|
73
|
-
protected
|
74
|
-
|
75
|
-
def html_attrs(attrs={})
|
76
|
-
raise ArgumentError unless attrs.kind_of? ::Hash
|
77
|
-
if attrs.empty?
|
78
|
-
''
|
79
|
-
else
|
80
|
-
' '+attrs.
|
81
|
-
sort {|a,b| a[0].to_s <=> b[0].to_s}.
|
82
|
-
collect {|k_v| "#{k_v[0]}=\"#{k_v[1]}\""}.
|
83
|
-
join(' ').
|
84
|
-
strip
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
94
|
private
|
89
95
|
|
90
|
-
def
|
91
|
-
|
92
|
-
|
93
|
-
|
96
|
+
def proxy(value, attrs, content_block)
|
97
|
+
yield value if block_given?
|
98
|
+
@attrs.merge!(attrs)
|
99
|
+
@content_blocks << content_block if content_block
|
100
|
+
@start_tag = start_tag
|
101
|
+
@end_tag = end_tag
|
94
102
|
self
|
95
103
|
end
|
96
104
|
|
97
|
-
def
|
98
|
-
self.
|
99
|
-
self.___attrs.merge!(attrs)
|
100
|
-
self.___content = block
|
101
|
-
self
|
105
|
+
def start_tag
|
106
|
+
"<#{@name}#{self.class.html_attrs(@attrs)}" + (@content_blocks.size > 0 ? ">" : " />")
|
102
107
|
end
|
103
108
|
|
104
|
-
def
|
105
|
-
|
106
|
-
@content_writes += 1
|
107
|
-
@stack.push(self)
|
108
|
-
block.call
|
109
|
-
@stack.pop
|
110
|
-
end
|
109
|
+
def end_tag
|
110
|
+
@content_blocks.size > 0 ? "</#{@name}>" : nil
|
111
111
|
end
|
112
112
|
|
113
113
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Undies
|
2
|
+
|
3
|
+
class Source; end
|
4
|
+
|
5
|
+
class NamedSource
|
6
|
+
|
7
|
+
attr_accessor :file, :opts, :proc
|
8
|
+
|
9
|
+
def initialize(*args, &block)
|
10
|
+
args << block if block
|
11
|
+
self.args = args
|
12
|
+
end
|
13
|
+
|
14
|
+
def ==(other_named_source)
|
15
|
+
self.file == other_named_source.file &&
|
16
|
+
self.opts == other_named_source.opts &&
|
17
|
+
self.proc == other_named_source.proc
|
18
|
+
end
|
19
|
+
|
20
|
+
def args=(values)
|
21
|
+
self.proc, self.opts, self.file = [
|
22
|
+
values.last.kind_of?(::Proc) ? values.pop : nil,
|
23
|
+
values.last.kind_of?(::Hash) ? values.pop : {},
|
24
|
+
values.last.kind_of?(::String) ? values.pop : nil
|
25
|
+
]
|
26
|
+
end
|
27
|
+
|
28
|
+
def args
|
29
|
+
[self.file, self.opts, self.proc]
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
# singleton accessors for named sources
|
35
|
+
|
36
|
+
def self.named_sources
|
37
|
+
@@sources ||= {}
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.named_source(name, *args, &block)
|
41
|
+
if args.empty? && block.nil?
|
42
|
+
self.named_sources[name]
|
43
|
+
else
|
44
|
+
self.named_sources[name] = Undies::NamedSource.new(*args, &block)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.source(name)
|
49
|
+
if ns = self.named_source(name)
|
50
|
+
Undies::Source.new(ns)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
data/lib/undies/node.rb
CHANGED
@@ -1,37 +1,29 @@
|
|
1
1
|
module Undies
|
2
|
-
class Node
|
3
2
|
|
4
|
-
|
3
|
+
class Node
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
# have as many methods to the class level as possilbe to keep from
|
6
|
+
# polluting the public instance methods and to maximize the effectiveness
|
7
|
+
# of the Element#method_missing logic
|
9
8
|
|
10
|
-
def
|
11
|
-
|
9
|
+
def self.content(node)
|
10
|
+
node.instance_variable_get("@content")
|
12
11
|
end
|
13
12
|
|
14
|
-
def
|
15
|
-
|
13
|
+
def self.flush(output, node)
|
14
|
+
output << self.content(node)
|
16
15
|
end
|
17
16
|
|
18
|
-
def
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
].compact.collect do |item|
|
23
|
-
pretty_print(item, pp_level, pp_indent)
|
24
|
-
end.join
|
17
|
+
def initialize(content)
|
18
|
+
@start_tag = nil
|
19
|
+
@end_tag = nil
|
20
|
+
@content = content
|
25
21
|
end
|
26
22
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
data.to_s(level+1, indent)
|
32
|
-
else
|
33
|
-
indent ? "#{' '*level*indent}#{data}\n" : data
|
34
|
-
end
|
23
|
+
def ==(other_node)
|
24
|
+
self.class.content(self) == other_node.class.content(other_node) &&
|
25
|
+
self.instance_variable_get("@start_tag") == other_node.instance_variable_get("@start_tag") &&
|
26
|
+
self.instance_variable_get("@end_tag") == other_node.instance_variable_get("@end_tag")
|
35
27
|
end
|
36
28
|
|
37
29
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Undies
|
2
|
+
|
3
|
+
class NodeBuffer < ::Array
|
4
|
+
|
5
|
+
# a node buffer is a FIFO used to, well, buffer node data for output.
|
6
|
+
# nodes are pushed on the stack for processing and flushed to output
|
7
|
+
# when pulled. empty the buffer by flushing it to output.
|
8
|
+
|
9
|
+
# the buffer allows for dynamic node handling while limiting memory
|
10
|
+
# bloat. the Output handler ensures that only 1 node is buffered
|
11
|
+
# in memory at any given time by pulling the previous node to output
|
12
|
+
# before pushing the next node for processing.
|
13
|
+
|
14
|
+
def initialize(*args)
|
15
|
+
# always initialize empty
|
16
|
+
super()
|
17
|
+
end
|
18
|
+
|
19
|
+
def push(node)
|
20
|
+
super
|
21
|
+
node
|
22
|
+
end
|
23
|
+
|
24
|
+
def pull(output)
|
25
|
+
if (node = self.shift)
|
26
|
+
node.class.flush(output, node)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def flush(output)
|
31
|
+
self.pull(output) while self.size > 0
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'undies/node'
|
2
|
+
require 'undies/element'
|
3
|
+
require 'undies/node_buffer'
|
4
|
+
|
5
|
+
module Undies
|
6
|
+
class Output
|
7
|
+
|
8
|
+
attr_reader :io, :options, :pp, :node_buffer
|
9
|
+
|
10
|
+
# the output class wraps an IO stream, gathers pretty printing options,
|
11
|
+
# and handles buffering nodes and pretty printing to the stream
|
12
|
+
|
13
|
+
def initialize(io, opts={})
|
14
|
+
@io = io
|
15
|
+
self.options = opts
|
16
|
+
@node_buffer = NodeBuffer.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def options=(opts)
|
20
|
+
if !opts.kind_of?(::Hash)
|
21
|
+
raise ArgumentError, "please provide a hash to set options with"
|
22
|
+
end
|
23
|
+
|
24
|
+
# setup any pretty printing
|
25
|
+
@pp = opts[:pp]
|
26
|
+
self.pp_level = 0
|
27
|
+
self.pp_use_indent = true
|
28
|
+
|
29
|
+
@options = opts
|
30
|
+
end
|
31
|
+
|
32
|
+
def pp_level
|
33
|
+
@pp_level
|
34
|
+
end
|
35
|
+
|
36
|
+
def pp_level=(value)
|
37
|
+
@pp_indent = @pp ? "\n#{' '*value*@pp}" : ""
|
38
|
+
@pp_level = value
|
39
|
+
end
|
40
|
+
|
41
|
+
def pp_use_indent=(value)
|
42
|
+
@pp_use_indent = value
|
43
|
+
end
|
44
|
+
|
45
|
+
def <<(data)
|
46
|
+
@io << (@pp_use_indent ? "#{@pp_indent}#{data}" : data.to_s)
|
47
|
+
end
|
48
|
+
|
49
|
+
def node(data="")
|
50
|
+
self.node_buffer.pull(self)
|
51
|
+
self.node_buffer.push(Node.new(data))
|
52
|
+
end
|
53
|
+
|
54
|
+
def element(name, attrs={}, &block)
|
55
|
+
self.node_buffer.pull(self)
|
56
|
+
self.node_buffer.push(Element.new(name, attrs, &block))
|
57
|
+
end
|
58
|
+
|
59
|
+
def flush
|
60
|
+
self.node_buffer.flush(self)
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|