undies 0.0.1 → 1.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/Gemfile.lock +1 -1
- data/lib/undies/{tag.rb → element.rb} +38 -18
- data/lib/undies/node.rb +38 -0
- data/lib/undies/node_list.rb +28 -0
- data/lib/undies/partial.rb +20 -0
- data/lib/undies/partial_data.rb +32 -0
- data/lib/undies/source.rb +12 -10
- data/lib/undies/template.rb +100 -8
- data/lib/undies/version.rb +1 -1
- data/test/{tag_test.rb → element_test.rb} +58 -26
- data/test/node_list_test.rb +48 -0
- data/test/node_test.rb +24 -0
- data/test/partial_data_test.rb +100 -0
- data/test/partial_test.rb +41 -0
- data/test/source_test.rb +14 -5
- data/test/template_test.rb +128 -4
- data/test/templates/index.html.rb +0 -0
- metadata +23 -12
- data/lib/undies/buffer.rb +0 -81
- data/test/buffer_test.rb +0 -79
- /data/test/{test_template.html.rb → templates/test.html.rb} +0 -0
data/Gemfile.lock
CHANGED
@@ -1,17 +1,30 @@
|
|
1
|
-
require 'undies/
|
1
|
+
require 'undies/node'
|
2
|
+
require 'undies/node_list'
|
2
3
|
|
3
4
|
module Undies
|
4
|
-
class
|
5
|
+
class Element < Node
|
5
6
|
|
6
|
-
attr_reader :attrs
|
7
|
+
attr_reader :name, :attrs
|
8
|
+
attr_accessor :nodes
|
7
9
|
|
8
|
-
def initialize(name
|
9
|
-
super
|
10
|
-
@
|
10
|
+
def initialize(stack, name, attrs={}, &block)
|
11
|
+
super(@nodes = NodeList.new)
|
12
|
+
@stack = stack
|
13
|
+
@name = name.to_s
|
11
14
|
@attrs = attrs
|
15
|
+
@content_writes = 0
|
12
16
|
self.content = block
|
13
17
|
end
|
14
18
|
|
19
|
+
def start_tag
|
20
|
+
"<#{@name}#{html_attrs(@attrs)}" + (@content_writes > 0 ? ">" : " />")
|
21
|
+
end
|
22
|
+
|
23
|
+
def end_tag
|
24
|
+
@content_writes > 0 ? "</#{@name}>" : nil
|
25
|
+
end
|
26
|
+
|
27
|
+
# CSS proxy methods ============================================
|
15
28
|
ID_METH_REGEX = /^([^_].+)!$/
|
16
29
|
CLASS_METH_REGEX = /^([^_].+)$/
|
17
30
|
|
@@ -32,17 +45,22 @@ module Undies
|
|
32
45
|
super
|
33
46
|
end
|
34
47
|
end
|
48
|
+
# ==============================================================
|
35
49
|
|
36
|
-
def
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
50
|
+
def ==(other)
|
51
|
+
other.name == self.name &&
|
52
|
+
other.attrs == self.attrs &&
|
53
|
+
other.nodes == self.nodes
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_str(*args)
|
57
|
+
"Undies::Element:#{self.object_id} " +
|
58
|
+
"@name=#{@name.inspect}, @attrs=#{@attrs.inspect}, @nodes=#{@nodes.inspect}"
|
59
|
+
end
|
60
|
+
alias_method :inspect, :to_str
|
61
|
+
|
62
|
+
def to_ary(*args)
|
63
|
+
@nodes
|
46
64
|
end
|
47
65
|
|
48
66
|
protected
|
@@ -78,8 +96,10 @@ module Undies
|
|
78
96
|
|
79
97
|
def content=(block)
|
80
98
|
if block
|
81
|
-
@
|
82
|
-
|
99
|
+
@content_writes += 1
|
100
|
+
@stack.push(self)
|
101
|
+
block.call
|
102
|
+
@stack.pop
|
83
103
|
end
|
84
104
|
end
|
85
105
|
|
data/lib/undies/node.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
module Undies
|
2
|
+
class Node
|
3
|
+
|
4
|
+
attr_reader :content
|
5
|
+
|
6
|
+
def initialize(content)
|
7
|
+
@content = content
|
8
|
+
end
|
9
|
+
|
10
|
+
def start_tag
|
11
|
+
nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def end_tag
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_s(pp_level=0, pp_indent=nil)
|
19
|
+
[ self.start_tag,
|
20
|
+
self.content,
|
21
|
+
self.end_tag
|
22
|
+
].compact.collect do |item|
|
23
|
+
pretty_print(item, pp_level, pp_indent)
|
24
|
+
end.join
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def pretty_print(data, level, indent)
|
30
|
+
if data.kind_of? NodeList
|
31
|
+
data.to_s(level+1, indent)
|
32
|
+
else
|
33
|
+
indent ? "#{' '*level*indent}#{data}\n" : data
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "undies/node"
|
2
|
+
|
3
|
+
module Undies
|
4
|
+
class NodeList < ::Array
|
5
|
+
|
6
|
+
def initialize(*args)
|
7
|
+
#always initialize empty
|
8
|
+
super()
|
9
|
+
end
|
10
|
+
|
11
|
+
def append(node)
|
12
|
+
self << node
|
13
|
+
node
|
14
|
+
end
|
15
|
+
|
16
|
+
def <<(item)
|
17
|
+
unless item.kind_of?(Node)
|
18
|
+
raise ArgumentError, 'you can only append nodes to a NodeList'
|
19
|
+
end
|
20
|
+
super
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s(pp_level=0, pp_indent=nil)
|
24
|
+
self.collect{|n| n.to_s(pp_level, pp_indent)}.join
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'undies/partial_data'
|
2
|
+
require 'undies/template'
|
3
|
+
|
4
|
+
module Undies
|
5
|
+
class Partial < Template
|
6
|
+
|
7
|
+
def initialize(path, object=nil, locals={})
|
8
|
+
data = PartialData.new(path)
|
9
|
+
data.object, data.values = object_locals(object, locals)
|
10
|
+
super(path, data)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def object_locals(o, l)
|
16
|
+
o && o.kind_of?(::Hash) ? [nil, o] : [o, l || {}]
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Undies
|
2
|
+
class PartialData < ::Hash
|
3
|
+
|
4
|
+
attr_reader :path, :name
|
5
|
+
|
6
|
+
def initialize(path)
|
7
|
+
self.path = path
|
8
|
+
super()
|
9
|
+
end
|
10
|
+
|
11
|
+
def path=(value)
|
12
|
+
raise ArgumentError, "partial path required" if value.nil?
|
13
|
+
@path = value
|
14
|
+
@name = File.basename(@path.to_s).split(".").first.gsub(/^[^A-Za-z]+/, '')
|
15
|
+
end
|
16
|
+
|
17
|
+
def values=(value)
|
18
|
+
raise ArgumentError if !value.kind_of?(::Hash)
|
19
|
+
if value.has_key?(@name.to_sym)
|
20
|
+
value[@name] = value.delete(@name.to_sym)
|
21
|
+
end
|
22
|
+
self.merge!(value)
|
23
|
+
end
|
24
|
+
|
25
|
+
def object=(value)
|
26
|
+
if value
|
27
|
+
self[@name] = value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
data/lib/undies/source.rb
CHANGED
@@ -1,24 +1,26 @@
|
|
1
1
|
module Undies
|
2
2
|
class Source
|
3
3
|
|
4
|
-
attr_reader :
|
4
|
+
attr_reader :source, :data
|
5
5
|
|
6
|
-
def initialize(
|
7
|
-
raise ArgumentError, "file or block required" if
|
6
|
+
def initialize(source=nil)
|
7
|
+
raise ArgumentError, "file or block required" if source.nil?
|
8
8
|
|
9
|
-
@
|
10
|
-
|
9
|
+
@source = source
|
10
|
+
if self.file? && !File.exists?(@source.to_s)
|
11
|
+
raise ArgumentError, "no template file '#{@source}'"
|
12
|
+
end
|
11
13
|
|
12
|
-
# load
|
13
|
-
@data =
|
14
|
-
File.binread
|
14
|
+
# load source data and prepare (uses binread to avoid encoding issues)
|
15
|
+
@data = if self.file?
|
16
|
+
File.send(File.respond_to?(:binread) ? :binread : :read, @source.to_s)
|
15
17
|
else
|
16
|
-
|
18
|
+
@source
|
17
19
|
end
|
18
20
|
end
|
19
21
|
|
20
22
|
def file?
|
21
|
-
|
23
|
+
!@source.kind_of?(::Proc)
|
22
24
|
end
|
23
25
|
|
24
26
|
end
|
data/lib/undies/template.rb
CHANGED
@@ -1,22 +1,114 @@
|
|
1
1
|
require 'undies/source'
|
2
|
-
require 'undies/
|
3
|
-
require 'undies/
|
2
|
+
require 'undies/node'
|
3
|
+
require 'undies/element'
|
4
4
|
|
5
5
|
module Undies
|
6
|
-
class Template
|
6
|
+
class Template
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
attr_accessor :nodes
|
9
|
+
|
10
|
+
def initialize(*args, &block)
|
11
|
+
@nodes = NodeList.new
|
12
|
+
@stack = [self]
|
13
|
+
self.data, @source = data_source(args, block)
|
14
|
+
|
15
|
+
if (@source).file?
|
16
|
+
instance_eval(@source.data, @source.source, 1)
|
12
17
|
else
|
13
18
|
instance_eval(&@source.data)
|
14
19
|
end
|
15
20
|
end
|
16
21
|
|
17
22
|
def to_s(pp_indent=nil)
|
18
|
-
|
23
|
+
@nodes.collect{|n| n.to_s(0, pp_indent)}.join
|
24
|
+
end
|
25
|
+
|
26
|
+
# Add a text node (data escaped) to the nodes of the current node
|
27
|
+
def _(data)
|
28
|
+
@stack.last.nodes.append(Node.new(escape_html(data.to_s)))
|
29
|
+
end
|
30
|
+
|
31
|
+
# Add a text node with the data un-escaped
|
32
|
+
def __(data)
|
33
|
+
@stack.last.nodes.append(Node.new(data.to_s))
|
34
|
+
end
|
35
|
+
|
36
|
+
# Add an element to the nodes of the current node
|
37
|
+
def element(name, attrs={}, &block)
|
38
|
+
@stack.last.nodes.append(Element.new(@stack, name, attrs, &block))
|
39
|
+
end
|
40
|
+
alias_method :tag, :element
|
41
|
+
|
42
|
+
# Element proxy methods ('_<element>'') ========================
|
43
|
+
ELEM_METH_REGEX = /^_(.+)$/
|
44
|
+
|
45
|
+
def method_missing(meth, *args, &block)
|
46
|
+
if meth.to_s =~ ELEM_METH_REGEX
|
47
|
+
element($1, *args, &block)
|
48
|
+
else
|
49
|
+
super
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def respond_to?(*args)
|
54
|
+
if args.first.to_s =~ ELEM_METH_REGEX
|
55
|
+
true
|
56
|
+
else
|
57
|
+
super
|
58
|
+
end
|
19
59
|
end
|
60
|
+
# ==============================================================
|
61
|
+
|
62
|
+
protected
|
63
|
+
|
64
|
+
def data=(data)
|
65
|
+
raise ArgumentError if !data.kind_of?(::Hash)
|
66
|
+
data.each do |key, value|
|
67
|
+
metaclass do
|
68
|
+
define_method(key) { value }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def source
|
74
|
+
@source
|
75
|
+
end
|
76
|
+
|
77
|
+
def stack
|
78
|
+
@stack
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def data_source(args, block)
|
84
|
+
[ args.last.kind_of?(::Hash) ? args.pop : {},
|
85
|
+
Source.new(block || args.first.to_s)
|
86
|
+
]
|
87
|
+
end
|
88
|
+
|
89
|
+
def metaclass(&block)
|
90
|
+
metaclass = class << self; self; end
|
91
|
+
metaclass.class_eval(&block)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Ripped from Rack v1.3.0 ======================================
|
95
|
+
# => ripped b/c I don't want a dependency on Rack for just this
|
96
|
+
ESCAPE_HTML = {
|
97
|
+
"&" => "&",
|
98
|
+
"<" => "<",
|
99
|
+
">" => ">",
|
100
|
+
"'" => "'",
|
101
|
+
'"' => """,
|
102
|
+
"/" => "/"
|
103
|
+
}
|
104
|
+
ESCAPE_HTML_PATTERN = Regexp.union(*ESCAPE_HTML.keys)
|
105
|
+
|
106
|
+
# Escape ampersands, brackets and quotes to their HTML/XML entities.
|
107
|
+
def escape_html(string)
|
108
|
+
string.to_s.gsub(ESCAPE_HTML_PATTERN){|c| ESCAPE_HTML[c] }
|
109
|
+
end
|
110
|
+
# end Rip from Rack v1.3.0 =====================================
|
111
|
+
|
20
112
|
|
21
113
|
end
|
22
114
|
end
|
data/lib/undies/version.rb
CHANGED
@@ -1,16 +1,47 @@
|
|
1
1
|
require "test/helper"
|
2
|
-
require "undies/
|
2
|
+
require "undies/element"
|
3
3
|
|
4
|
-
class Undies::
|
4
|
+
class Undies::Element
|
5
5
|
|
6
6
|
|
7
7
|
|
8
8
|
class BasicTest < Test::Unit::TestCase
|
9
9
|
include TestBelt
|
10
10
|
|
11
|
-
context '
|
12
|
-
subject { Undies::
|
13
|
-
should
|
11
|
+
context 'an element'
|
12
|
+
subject { Undies::Element.new([], :div) }
|
13
|
+
should have_readers :name, :attrs
|
14
|
+
should have_accessor :nodes
|
15
|
+
|
16
|
+
should "be a Node" do
|
17
|
+
assert_kind_of Undies::Node, subject
|
18
|
+
end
|
19
|
+
|
20
|
+
should "store it's name as a string" do
|
21
|
+
assert_equal "div", subject.name
|
22
|
+
end
|
23
|
+
|
24
|
+
should "have a NodeList as its nodes" do
|
25
|
+
assert_kind_of Undies::NodeList, subject.nodes
|
26
|
+
end
|
27
|
+
|
28
|
+
should "have its nodes be its content" do
|
29
|
+
assert_equal subject.nodes.object_id, subject.content.object_id
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
class EmptyTest < Test::Unit::TestCase
|
37
|
+
include TestBelt
|
38
|
+
context 'an empty element'
|
39
|
+
subject { Undies::Element.new([], :br) }
|
40
|
+
|
41
|
+
should "have no nodes" do
|
42
|
+
assert_equal([], subject.nodes)
|
43
|
+
end
|
44
|
+
|
14
45
|
end
|
15
46
|
|
16
47
|
|
@@ -44,27 +75,28 @@ class Undies::Tag
|
|
44
75
|
|
45
76
|
|
46
77
|
class SerializeTest < BasicTest
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
tag = Undies::Tag.new(:br)
|
51
|
-
assert_equal "<br />", tag.to_s
|
78
|
+
should "serialize with no child elements" do
|
79
|
+
element = Undies::Element.new([], :br)
|
80
|
+
assert_equal "<br />", element.to_s
|
52
81
|
end
|
53
82
|
|
54
|
-
should "
|
55
|
-
|
56
|
-
assert_equal '<br class="big" />',
|
83
|
+
should "serialize with attrs" do
|
84
|
+
element = Undies::Element.new([], :br, {:class => 'big'})
|
85
|
+
assert_equal '<br class="big" />', element.to_s
|
57
86
|
end
|
58
87
|
|
59
|
-
should "
|
60
|
-
|
61
|
-
|
88
|
+
should "serialize with attrs and content" do
|
89
|
+
templ = Undies::Template.new do
|
90
|
+
element(:strong, {:class => 'big'}) { __ "Loud Noises!" }
|
91
|
+
end
|
92
|
+
assert_equal '<strong class="big">Loud Noises!</strong>', templ.to_s
|
62
93
|
end
|
63
94
|
end
|
64
95
|
|
65
96
|
|
66
97
|
|
67
98
|
class CSSProxyTest < BasicTest
|
99
|
+
|
68
100
|
should "respond to any method ending in '!' as an id proxy" do
|
69
101
|
assert subject.respond_to?(:asdgasdg!)
|
70
102
|
end
|
@@ -75,11 +107,11 @@ class Undies::Tag
|
|
75
107
|
}, subject.thing1!.attrs)
|
76
108
|
end
|
77
109
|
|
78
|
-
should "nest
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
110
|
+
should "nest elements from proxy id call" do
|
111
|
+
templ = Undies::Template.new do
|
112
|
+
element(:div).thing1! { _ "stuff" }
|
113
|
+
end
|
114
|
+
assert_equal "<div id=\"thing1\">stuff</div>", templ.to_s
|
83
115
|
end
|
84
116
|
|
85
117
|
should "proxy id attr with last method call ending in '!'" do
|
@@ -110,11 +142,11 @@ class Undies::Tag
|
|
110
142
|
}, subject.thing.attrs)
|
111
143
|
end
|
112
144
|
|
113
|
-
should "nest
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
145
|
+
should "nest elements from proxy class call" do
|
146
|
+
templ = Undies::Template.new do
|
147
|
+
element(:div).thing { _ "stuff" }
|
148
|
+
end
|
149
|
+
assert_equal "<div class=\"thing\">stuff</div>", templ.to_s
|
118
150
|
end
|
119
151
|
|
120
152
|
should "proxy multi html class attrs" do
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require "test/helper"
|
2
|
+
require "undies/node_list"
|
3
|
+
require "undies/node"
|
4
|
+
|
5
|
+
class Undies::NodeList
|
6
|
+
|
7
|
+
class BasicTest < Test::Unit::TestCase
|
8
|
+
include TestBelt
|
9
|
+
|
10
|
+
context 'a node list'
|
11
|
+
subject { Undies::NodeList.new }
|
12
|
+
should have_instance_method :append
|
13
|
+
|
14
|
+
should "be an Array" do
|
15
|
+
assert_kind_of ::Array, subject
|
16
|
+
end
|
17
|
+
|
18
|
+
should "always init empty" do
|
19
|
+
assert_equal 0, subject.size
|
20
|
+
assert_equal 0, Undies::NodeList.new([1,2,3]).size
|
21
|
+
end
|
22
|
+
|
23
|
+
should "complain if you try to append something other than a node" do
|
24
|
+
assert_raises ArgumentError do
|
25
|
+
subject.append('hey!')
|
26
|
+
end
|
27
|
+
assert_raises ArgumentError do
|
28
|
+
subject << 'hey!'
|
29
|
+
end
|
30
|
+
assert_nothing_raised do
|
31
|
+
subject.append(Undies::Node.new('hey!'))
|
32
|
+
subject << Undies::Node.new('hey!')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
should "append nodes with the 'append' method" do
|
37
|
+
subject.append(Undies::Node.new "hey!")
|
38
|
+
assert_equal 1, subject.size
|
39
|
+
end
|
40
|
+
|
41
|
+
should "return the node when appending" do
|
42
|
+
node = Undies::Node.new "hey!"
|
43
|
+
assert_equal node.object_id, subject.append(node).object_id
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
data/test/node_test.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require "test/helper"
|
2
|
+
require "undies/node"
|
3
|
+
|
4
|
+
class Undies::Node
|
5
|
+
|
6
|
+
class BasicTest < Test::Unit::TestCase
|
7
|
+
include TestBelt
|
8
|
+
|
9
|
+
context 'a node'
|
10
|
+
subject { Undies::Node.new("a text node here") }
|
11
|
+
should have_instance_method :to_s, :start_tag, :end_tag
|
12
|
+
should have_reader :content
|
13
|
+
|
14
|
+
should "know it's content" do
|
15
|
+
assert_equal "a text node here", subject.content.to_s
|
16
|
+
end
|
17
|
+
|
18
|
+
should "know how to serialize itself" do
|
19
|
+
assert_equal "a text node here", subject.to_s
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require "test/helper"
|
2
|
+
require "undies/partial_data"
|
3
|
+
|
4
|
+
class Undies::PartialData
|
5
|
+
|
6
|
+
class BasicTest < Test::Unit::TestCase
|
7
|
+
include TestBelt
|
8
|
+
|
9
|
+
context 'partial data'
|
10
|
+
subject { Undies::PartialData.new 'test/templates/index.html.rb' }
|
11
|
+
should have_readers :path, :name
|
12
|
+
|
13
|
+
should "be a kind of Hash" do
|
14
|
+
assert subject.kind_of?(::Hash)
|
15
|
+
end
|
16
|
+
|
17
|
+
should "complain if now path given" do
|
18
|
+
assert_raises ArgumentError do
|
19
|
+
Undies::PartialData.new
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
class NameTest < BasicTest
|
26
|
+
|
27
|
+
should "know its name given a file" do
|
28
|
+
data = Undies::PartialData.new('test/templates/current.html.rb')
|
29
|
+
assert_equal 'current', data.name
|
30
|
+
end
|
31
|
+
|
32
|
+
should "know its name given a file name with a leading char" do
|
33
|
+
data = Undies::PartialData.new('test/templates/_partial.html.rb')
|
34
|
+
assert_equal 'partial', data.name
|
35
|
+
end
|
36
|
+
|
37
|
+
should "know its name given a file name with multiple leading chars" do
|
38
|
+
data = Undies::PartialData.new('test/templates/__partial.html.rb')
|
39
|
+
assert_equal 'partial', data.name
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
class ValuesTest < BasicTest
|
45
|
+
before do
|
46
|
+
@path = 'test/templates/index.html.rb'
|
47
|
+
end
|
48
|
+
subject { Undies::PartialData.new(@path) }
|
49
|
+
|
50
|
+
should "not have any values by default" do
|
51
|
+
assert_equal({}, subject)
|
52
|
+
end
|
53
|
+
|
54
|
+
should "know its values" do
|
55
|
+
subject.values = {:name => 'A Name'}
|
56
|
+
assert_equal({:name => "A Name"}, subject)
|
57
|
+
end
|
58
|
+
|
59
|
+
should "complain when values not given as a hash" do
|
60
|
+
assert_raises ArgumentError do
|
61
|
+
subject.values = "some data"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
should "force its object value to a string key" do
|
66
|
+
assert !subject.has_key?(:index)
|
67
|
+
assert !subject.has_key?('index')
|
68
|
+
subject.object = "thing"
|
69
|
+
assert !subject.has_key?(:index)
|
70
|
+
assert subject.has_key?('index')
|
71
|
+
end
|
72
|
+
|
73
|
+
should "force its name value to a string key" do
|
74
|
+
assert !subject.has_key?(:index)
|
75
|
+
assert !subject.has_key?('index')
|
76
|
+
subject.values = {:index => 'thing'}
|
77
|
+
assert !subject.has_key?(:index)
|
78
|
+
assert subject.has_key?('index')
|
79
|
+
end
|
80
|
+
|
81
|
+
should "set its values to its object" do
|
82
|
+
subject.object = "thing"
|
83
|
+
assert_equal({'index' => "thing"}, subject)
|
84
|
+
end
|
85
|
+
|
86
|
+
should "merge its object into the values" do
|
87
|
+
subject.object = "thing"
|
88
|
+
subject.values = {:color => "#FFF"}
|
89
|
+
assert_equal({'index' => "thing", :color => "#FFF"}, subject)
|
90
|
+
end
|
91
|
+
|
92
|
+
should "overwrite its object with the values if needed" do
|
93
|
+
subject.object = "thing"
|
94
|
+
subject.values = {'index' => "#FFF"}
|
95
|
+
assert_equal({'index' => "#FFF"}, subject)
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "test/helper"
|
2
|
+
require "undies/partial"
|
3
|
+
|
4
|
+
class Undies::Partial
|
5
|
+
|
6
|
+
class BasicTest < Test::Unit::TestCase
|
7
|
+
include TestBelt
|
8
|
+
|
9
|
+
context 'partial'
|
10
|
+
subject { Undies::Partial.new 'test/templates/index.html.rb' }
|
11
|
+
|
12
|
+
should "be a kind of Template" do
|
13
|
+
assert subject.kind_of?(Undies::Template)
|
14
|
+
end
|
15
|
+
|
16
|
+
should "complain if no path given" do
|
17
|
+
assert_raises ArgumentError do
|
18
|
+
Undies::Partial.new
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
class LocalsTest < BasicTest
|
25
|
+
before do
|
26
|
+
@path = 'test/templates/index.html.rb'
|
27
|
+
end
|
28
|
+
|
29
|
+
should "know its data" do
|
30
|
+
partial = Undies::Partial.new(@path, :name => 'A Name')
|
31
|
+
assert_equal("A Name", partial.name)
|
32
|
+
end
|
33
|
+
|
34
|
+
should "know its object" do
|
35
|
+
partial = Undies::Partial.new(@path, "thing")
|
36
|
+
assert_equal("thing", partial.index)
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
data/test/source_test.rb
CHANGED
@@ -7,36 +7,45 @@ class Undies::Source
|
|
7
7
|
include TestBelt
|
8
8
|
|
9
9
|
context 'a source'
|
10
|
-
subject { Undies::Source.new(
|
10
|
+
subject { Undies::Source.new(Proc.new {}) }
|
11
|
+
should have_readers :source, :data
|
11
12
|
should have_instance_method :file?
|
12
|
-
should have_readers :file, :block, :data
|
13
13
|
|
14
|
-
should "
|
14
|
+
should "complain if no file or block given" do
|
15
15
|
assert_raises ArgumentError do
|
16
16
|
Undies::Source.new
|
17
17
|
end
|
18
18
|
end
|
19
|
+
|
20
|
+
should "complain if no block given and file does not exist" do
|
21
|
+
assert_raises ArgumentError do
|
22
|
+
Undies::Template.new "noexist.html.rb"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
19
26
|
end
|
20
27
|
|
21
28
|
class BlockTest < BasicTest
|
22
29
|
context 'from a block'
|
23
|
-
subject { Undies::Source.new(
|
30
|
+
subject { Undies::Source.new(Proc.new {}) }
|
24
31
|
|
25
32
|
should "not be a file source" do
|
26
33
|
assert !subject.file?
|
27
34
|
end
|
35
|
+
|
28
36
|
end
|
29
37
|
|
30
38
|
class FileTest < BasicTest
|
31
39
|
context 'from a file'
|
32
40
|
subject do
|
33
|
-
file = 'test/
|
41
|
+
file = 'test/templates/test.html.rb'
|
34
42
|
Undies::Source.new(File.expand_path(file))
|
35
43
|
end
|
36
44
|
|
37
45
|
should "be a file source" do
|
38
46
|
assert subject.file?
|
39
47
|
end
|
48
|
+
|
40
49
|
end
|
41
50
|
|
42
51
|
end
|
data/test/template_test.rb
CHANGED
@@ -6,12 +6,136 @@ class Undies::Template
|
|
6
6
|
class BasicTest < Test::Unit::TestCase
|
7
7
|
include TestBelt
|
8
8
|
|
9
|
-
context 'template'
|
9
|
+
context 'a template'
|
10
10
|
subject { Undies::Template.new {} }
|
11
|
-
should
|
11
|
+
should have_instance_method :to_s
|
12
|
+
should have_instance_methods :_, :__, :element, :tag
|
13
|
+
should have_accessor :nodes
|
14
|
+
|
15
|
+
should "have a NodeList as its nodes" do
|
16
|
+
assert_kind_of Undies::NodeList, subject.nodes
|
17
|
+
end
|
18
|
+
|
12
19
|
end
|
13
20
|
|
21
|
+
|
22
|
+
|
23
|
+
class NodeTest < BasicTest
|
24
|
+
context "with text data"
|
25
|
+
before do
|
26
|
+
@data = "stuff & <em>more stuff</em>"
|
27
|
+
end
|
28
|
+
|
29
|
+
should "return a text node using the '__' and '_' methods" do
|
30
|
+
assert_kind_of Undies::Node, subject.__(@data)
|
31
|
+
assert_kind_of Undies::Node, subject._(@data)
|
32
|
+
end
|
33
|
+
|
34
|
+
should "also add the node using the '__' and '_' methods" do
|
35
|
+
subject.__(@data)
|
36
|
+
assert_equal 1, subject.nodes.size
|
37
|
+
subject._(@data)
|
38
|
+
assert_equal 2, subject.nodes.size
|
39
|
+
end
|
40
|
+
|
41
|
+
should "add the text un-escaped using the '__' method" do
|
42
|
+
assert_equal @data, subject.__(@data).to_s
|
43
|
+
end
|
44
|
+
|
45
|
+
should "add the text escaped using the '_' method" do
|
46
|
+
assert_equal subject.send(:escape_html, @data), subject._(@data).to_s
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
class ElementTest < BasicTest
|
54
|
+
context "using the 'element' helper"
|
55
|
+
|
56
|
+
should "return an Element object" do
|
57
|
+
assert_equal Undies::Element.new([], :br), subject.element(:br)
|
58
|
+
end
|
59
|
+
|
60
|
+
should "alias it with 'tag'" do
|
61
|
+
assert_equal subject.element(:br), subject.tag(:br)
|
62
|
+
end
|
63
|
+
|
64
|
+
should "add a new Element object" do
|
65
|
+
subject.element(:br)
|
66
|
+
assert_equal 1, subject.nodes.size
|
67
|
+
assert_equal Undies::Element.new([], :br), subject.nodes.first
|
68
|
+
end
|
69
|
+
|
70
|
+
should "respond to underscore-prefix methods" do
|
71
|
+
assert subject.respond_to?(:_div)
|
72
|
+
end
|
73
|
+
|
74
|
+
should "respond to underscore-prefix methods as element methods" do
|
75
|
+
assert_equal subject._div, subject.element(:div)
|
76
|
+
end
|
77
|
+
|
78
|
+
should "not respond to element methods without an underscore-prefix" do
|
79
|
+
assert !subject.respond_to?(:div)
|
80
|
+
assert_raises NoMethodError do
|
81
|
+
subject.div
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
class DataTest < BasicTest
|
90
|
+
|
91
|
+
should "only accept the data if it is a Hash" do
|
92
|
+
assert_raises NoMethodError do
|
93
|
+
(Undies::Template.new("some_data") {}).some
|
94
|
+
end
|
95
|
+
assert_raises NoMethodError do
|
96
|
+
(Undies::Template.new('test/templates/test.html.rb', "some_data")).some
|
97
|
+
end
|
98
|
+
assert_respond_to(
|
99
|
+
(Undies::Template.new(:some => "data") {}),
|
100
|
+
:some
|
101
|
+
)
|
102
|
+
assert_respond_to(
|
103
|
+
Undies::Template.new('test/templates/test.html.rb', :some => "data"),
|
104
|
+
:some
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
108
|
+
should "respond to each data key with its value" do
|
109
|
+
templ = Undies::Template.new(:some => "data") {}
|
110
|
+
assert_equal "data", templ.some
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
|
14
117
|
class DefinitionTest < BasicTest
|
118
|
+
|
119
|
+
should "maintain the template's scope throughout content blocks" do
|
120
|
+
templ = Undies::Template.new do
|
121
|
+
_div {
|
122
|
+
_div {
|
123
|
+
__ self.object_id
|
124
|
+
}
|
125
|
+
}
|
126
|
+
end
|
127
|
+
assert_equal "<div><div>#{templ.object_id}</div></div>", templ.to_s
|
128
|
+
end
|
129
|
+
|
130
|
+
should "be able to access its data in the template definition" do
|
131
|
+
templ = Undies::Template.new(:name => "awesome") do
|
132
|
+
_div {
|
133
|
+
_div { _ name }
|
134
|
+
}
|
135
|
+
end
|
136
|
+
assert_equal "<div><div>awesome</div></div>", templ.to_s
|
137
|
+
end
|
138
|
+
|
15
139
|
should "generate markup given a block" do
|
16
140
|
assert_equal(
|
17
141
|
"<html><head></head><body><div class=\"loud element\" id=\"header\">YEA!!</div></body></html>",
|
@@ -29,7 +153,7 @@ class Undies::Template
|
|
29
153
|
end
|
30
154
|
|
31
155
|
should "generate markup given a file" do
|
32
|
-
file = 'test/
|
156
|
+
file = 'test/templates/test.html.rb'
|
33
157
|
assert_equal(
|
34
158
|
"<html><head></head><body><div class=\"file\">FILE!!</div></body></html>",
|
35
159
|
Undies::Template.new(File.expand_path(file)).to_s
|
@@ -37,7 +161,7 @@ class Undies::Template
|
|
37
161
|
end
|
38
162
|
|
39
163
|
should "generate pretty printed markup" do
|
40
|
-
file = 'test/
|
164
|
+
file = 'test/templates/test.html.rb'
|
41
165
|
assert_equal(
|
42
166
|
%{<html>
|
43
167
|
<head>
|
File without changes
|
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:
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
|
+
- 1
|
7
8
|
- 0
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 0.0.1
|
10
|
+
version: 1.0.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Kelly D. Redding
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-07-
|
18
|
+
date: 2011-07-25 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
requirement: &id001 !ruby/object:Gem::Requirement
|
@@ -64,18 +64,25 @@ files:
|
|
64
64
|
- README.rdoc
|
65
65
|
- Rakefile
|
66
66
|
- lib/undies.rb
|
67
|
-
- lib/undies/
|
67
|
+
- lib/undies/element.rb
|
68
|
+
- lib/undies/node.rb
|
69
|
+
- lib/undies/node_list.rb
|
70
|
+
- lib/undies/partial.rb
|
71
|
+
- lib/undies/partial_data.rb
|
68
72
|
- lib/undies/source.rb
|
69
|
-
- lib/undies/tag.rb
|
70
73
|
- lib/undies/template.rb
|
71
74
|
- lib/undies/version.rb
|
72
|
-
- test/
|
75
|
+
- test/element_test.rb
|
73
76
|
- test/env.rb
|
74
77
|
- test/helper.rb
|
78
|
+
- test/node_list_test.rb
|
79
|
+
- test/node_test.rb
|
80
|
+
- test/partial_data_test.rb
|
81
|
+
- test/partial_test.rb
|
75
82
|
- test/source_test.rb
|
76
|
-
- test/tag_test.rb
|
77
83
|
- test/template_test.rb
|
78
|
-
- test/
|
84
|
+
- test/templates/index.html.rb
|
85
|
+
- test/templates/test.html.rb
|
79
86
|
- undies.gemspec
|
80
87
|
homepage: http://github.com/kelredd/undies
|
81
88
|
licenses: []
|
@@ -111,10 +118,14 @@ signing_key:
|
|
111
118
|
specification_version: 3
|
112
119
|
summary: A pure-Ruby HTML templating DSL.
|
113
120
|
test_files:
|
114
|
-
- test/
|
121
|
+
- test/element_test.rb
|
115
122
|
- test/env.rb
|
116
123
|
- test/helper.rb
|
124
|
+
- test/node_list_test.rb
|
125
|
+
- test/node_test.rb
|
126
|
+
- test/partial_data_test.rb
|
127
|
+
- test/partial_test.rb
|
117
128
|
- test/source_test.rb
|
118
|
-
- test/tag_test.rb
|
119
129
|
- test/template_test.rb
|
120
|
-
- test/
|
130
|
+
- test/templates/index.html.rb
|
131
|
+
- test/templates/test.html.rb
|
data/lib/undies/buffer.rb
DELETED
@@ -1,81 +0,0 @@
|
|
1
|
-
module Undies
|
2
|
-
class Buffer < ::Array
|
3
|
-
|
4
|
-
def initialize(*args)
|
5
|
-
super()
|
6
|
-
end
|
7
|
-
|
8
|
-
# Add data and don't escape it
|
9
|
-
def __(data="")
|
10
|
-
append_item(data)
|
11
|
-
end
|
12
|
-
# Add data and escape it
|
13
|
-
def _(data="")
|
14
|
-
append_item(escape_html(data))
|
15
|
-
end
|
16
|
-
|
17
|
-
TAG_METH_REGEX = /^_(.+)$/
|
18
|
-
|
19
|
-
def method_missing(meth, *args, &block)
|
20
|
-
if meth.to_s =~ TAG_METH_REGEX
|
21
|
-
tag($1, *args, &block)
|
22
|
-
else
|
23
|
-
super
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def respond_to?(*args)
|
28
|
-
if args.first.to_s =~ TAG_METH_REGEX
|
29
|
-
true
|
30
|
-
else
|
31
|
-
super
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def tag(name, attrs={}, &block)
|
36
|
-
append_item(new_tag=Tag.new(name, attrs, &block))
|
37
|
-
new_tag
|
38
|
-
end
|
39
|
-
|
40
|
-
def to_s(pp_level=0, pp_indent=nil)
|
41
|
-
self.collect do |i|
|
42
|
-
begin
|
43
|
-
i.to_s(pp_level, pp_indent)
|
44
|
-
rescue ArgumentError => err
|
45
|
-
pretty_print(i.to_s, pp_level, pp_indent)
|
46
|
-
end
|
47
|
-
end.join
|
48
|
-
end
|
49
|
-
|
50
|
-
protected
|
51
|
-
|
52
|
-
def pretty_print(data, level, indent)
|
53
|
-
indent ? "#{' '*level*indent}#{data}\n" : data
|
54
|
-
end
|
55
|
-
|
56
|
-
private
|
57
|
-
|
58
|
-
def append_item(data)
|
59
|
-
self << data
|
60
|
-
end
|
61
|
-
|
62
|
-
# Ripped from Rack v1.3.0 ======================================
|
63
|
-
# => ripped b/c I don't want a dependency on Rack for just this
|
64
|
-
ESCAPE_HTML = {
|
65
|
-
"&" => "&",
|
66
|
-
"<" => "<",
|
67
|
-
">" => ">",
|
68
|
-
"'" => "'",
|
69
|
-
'"' => """,
|
70
|
-
"/" => "/"
|
71
|
-
}
|
72
|
-
ESCAPE_HTML_PATTERN = Regexp.union(*ESCAPE_HTML.keys)
|
73
|
-
|
74
|
-
# Escape ampersands, brackets and quotes to their HTML/XML entities.
|
75
|
-
def escape_html(string)
|
76
|
-
string.to_s.gsub(ESCAPE_HTML_PATTERN){|c| ESCAPE_HTML[c] }
|
77
|
-
end
|
78
|
-
# end Rip from Rack v1.3.0 =====================================
|
79
|
-
|
80
|
-
end
|
81
|
-
end
|
data/test/buffer_test.rb
DELETED
@@ -1,79 +0,0 @@
|
|
1
|
-
require "test/helper"
|
2
|
-
require "undies/buffer"
|
3
|
-
require "undies/tag"
|
4
|
-
|
5
|
-
class Undies::Buffer
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
class BasicTest < Test::Unit::TestCase
|
11
|
-
include TestBelt
|
12
|
-
|
13
|
-
context 'a buffer'
|
14
|
-
subject { Undies::Buffer.new }
|
15
|
-
should have_instance_methods :to_s, :_, :__, :tag
|
16
|
-
|
17
|
-
should "be a kind of ::Array" do
|
18
|
-
assert subject.kind_of?(::Array)
|
19
|
-
end
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
class DataTest < BasicTest
|
26
|
-
context "with data"
|
27
|
-
before do
|
28
|
-
@data = "stuff & <em>more stuff</em>"
|
29
|
-
end
|
30
|
-
|
31
|
-
should "add it un-escaped using the '__' method" do
|
32
|
-
subject.__ @data
|
33
|
-
assert_equal "stuff & <em>more stuff</em>", subject.to_s
|
34
|
-
end
|
35
|
-
|
36
|
-
should "add it escaped using the '_' method" do
|
37
|
-
subject._ @data
|
38
|
-
assert_equal "stuff & <em>more stuff</em>", subject.to_s
|
39
|
-
end
|
40
|
-
|
41
|
-
end
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
class TagTest < BasicTest
|
46
|
-
context "when using the tag method"
|
47
|
-
|
48
|
-
should "return a new Tag object" do
|
49
|
-
assert_equal Undies::Tag.new(:br), subject.tag(:br)
|
50
|
-
end
|
51
|
-
|
52
|
-
should "add a new Tag object" do
|
53
|
-
subject.tag(:br)
|
54
|
-
assert_equal Undies::Tag.new(:br), subject.first
|
55
|
-
end
|
56
|
-
|
57
|
-
should "respond to any underscore prefix method" do
|
58
|
-
assert subject.respond_to?(:_div)
|
59
|
-
end
|
60
|
-
|
61
|
-
should "not respond to tag methods without an underscore prefix" do
|
62
|
-
assert !subject.respond_to?(:div)
|
63
|
-
assert_raises NoMethodError do
|
64
|
-
subject.div
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
should "interpret underscore prefix methods as a tag" do
|
69
|
-
assert_equal subject._div, subject.tag(:div)
|
70
|
-
end
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
# TODO: pretty printing
|
77
|
-
|
78
|
-
|
79
|
-
end
|
File without changes
|