undies 0.0.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- undies (0.0.1)
4
+ undies (1.0.0)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
@@ -1,17 +1,30 @@
1
- require 'undies/buffer'
1
+ require 'undies/node'
2
+ require 'undies/node_list'
2
3
 
3
4
  module Undies
4
- class Tag < Buffer
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=nil, attrs={}, &block)
9
- super
10
- @name = name
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 to_s(pp_level=0, pp_indent=nil)
37
- out = ""
38
- if @content
39
- out << pretty_print("<#{@name}#{html_attrs(@attrs)}>", pp_level, pp_indent)
40
- out << super(pp_level+1, pp_indent)
41
- out << pretty_print("</#{@name}>", pp_level, pp_indent)
42
- else
43
- out << pretty_print("<#{@name}#{html_attrs(@attrs)} />", pp_level, pp_indent)
44
- end
45
- out
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
- @content = block
82
- instance_eval(&@content)
99
+ @content_writes += 1
100
+ @stack.push(self)
101
+ block.call
102
+ @stack.pop
83
103
  end
84
104
  end
85
105
 
@@ -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 :file, :block, :data
4
+ attr_reader :source, :data
5
5
 
6
- def initialize(file=nil, block=nil)
7
- raise ArgumentError, "file or block required" if (file || block).nil?
6
+ def initialize(source=nil)
7
+ raise ArgumentError, "file or block required" if source.nil?
8
8
 
9
- @file = file
10
- @block = block
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 template data and prepare (uses binread to avoid encoding issues)
13
- @data = @block || if File.respond_to?(:binread)
14
- File.binread(@file)
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
- File.read(@file)
18
+ @source
17
19
  end
18
20
  end
19
21
 
20
22
  def file?
21
- !!self.file
23
+ !@source.kind_of?(::Proc)
22
24
  end
23
25
 
24
26
  end
@@ -1,22 +1,114 @@
1
1
  require 'undies/source'
2
- require 'undies/buffer'
3
- require 'undies/tag'
2
+ require 'undies/node'
3
+ require 'undies/element'
4
4
 
5
5
  module Undies
6
- class Template < Buffer
6
+ class Template
7
7
 
8
- def initialize(file=nil, &block)
9
- super
10
- if (@source = Source.new(file, block)).file?
11
- instance_eval(@source.data, @source.file, 1)
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
- super(0, pp_indent)
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
+ "&" => "&amp;",
98
+ "<" => "&lt;",
99
+ ">" => "&gt;",
100
+ "'" => "&#x27;",
101
+ '"' => "&quot;",
102
+ "/" => "&#x2F;"
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
@@ -1,3 +1,3 @@
1
1
  module Undies
2
- VERSION = "0.0.1"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -1,16 +1,47 @@
1
1
  require "test/helper"
2
- require "undies/tag"
2
+ require "undies/element"
3
3
 
4
- class Undies::Tag
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 'a tag'
12
- subject { Undies::Tag.new(:div) }
13
- should have_instance_methods :to_s, :attrs
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
- context "when serialized"
48
-
49
- should "buffer an empty html tag with no attrs" do
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 "buffer an html tag with attrs" do
55
- tag = Undies::Tag.new(:br, {:class => 'big'})
56
- assert_equal '<br class="big" />', tag.to_s
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 "buffer an html tag with attrs and content" do
60
- tag = Undies::Tag.new(:strong, {:class => 'big'}) { __ "Loud Noises!" }
61
- assert_equal '<strong class="big">Loud Noises!</strong>', tag.to_s
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 tags from proxy id call" do
79
- assert_equal(
80
- "<div id=\"thing1\">stuff</div>",
81
- subject.thing1! { _ 'stuff' }.to_s
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 tags from proxy class call" do
114
- assert_equal(
115
- "<div class=\"thing\">stuff</div>",
116
- subject.thing { _ 'stuff' }.to_s
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(nil, Proc.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 "need a file or block to initialize" do
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(nil, Proc.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/test_template.html.rb'
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
@@ -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 have_instance_methods :to_s
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/test_template.html.rb'
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/test_template.html.rb'
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: 29
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
+ - 1
7
8
  - 0
8
9
  - 0
9
- - 1
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-22 00:00:00 Z
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/buffer.rb
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/buffer_test.rb
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/test_template.html.rb
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/buffer_test.rb
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/test_template.html.rb
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
- "&" => "&amp;",
66
- "<" => "&lt;",
67
- ">" => "&gt;",
68
- "'" => "&#x27;",
69
- '"' => "&quot;",
70
- "/" => "&#x2F;"
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 &amp; &lt;em&gt;more stuff&lt;&#x2F;em&gt;", 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