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