zafu 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +2 -0
- data/History.txt +9 -0
- data/README.rdoc +56 -0
- data/Rakefile +56 -0
- data/lib/zafu/all.rb +17 -0
- data/lib/zafu/compiler.rb +7 -0
- data/lib/zafu/controller_methods.rb +49 -0
- data/lib/zafu/handler.rb +57 -0
- data/lib/zafu/info.rb +4 -0
- data/lib/zafu/markup.rb +186 -0
- data/lib/zafu/mock_helper.rb +42 -0
- data/lib/zafu/node_context.rb +96 -0
- data/lib/zafu/parser.rb +564 -0
- data/lib/zafu/parsing_rules.rb +257 -0
- data/lib/zafu/process/ajax.rb +90 -0
- data/lib/zafu/process/conditional.rb +45 -0
- data/lib/zafu/process/context.rb +45 -0
- data/lib/zafu/process/html.rb +168 -0
- data/lib/zafu/process/ruby_less.rb +145 -0
- data/lib/zafu/template.rb +25 -0
- data/lib/zafu/test_helper.rb +19 -0
- data/lib/zafu.rb +7 -0
- data/rails/init.rb +1 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/test/markup_test.rb +232 -0
- data/test/mock/params.rb +19 -0
- data/test/node_context_test.rb +190 -0
- data/test/ruby_less_test.rb +37 -0
- data/test/test_helper.rb +9 -0
- data/test/zafu_test.rb +57 -0
- data/zafu.gemspec +83 -0
- metadata +124 -0
@@ -0,0 +1,145 @@
|
|
1
|
+
require 'rubyless'
|
2
|
+
|
3
|
+
module Zafu
|
4
|
+
module Process
|
5
|
+
module RubyLess
|
6
|
+
include ::RubyLess::SafeClass
|
7
|
+
# Actual method resolution. The lookup first starts in the current helper. If nothing is found there, it
|
8
|
+
# searches inside a 'helpers' module and finally looks into the current node_context.
|
9
|
+
# If nothing is found at this stage, we prepend the method with the current node and start over again.
|
10
|
+
def safe_method_type(signature)
|
11
|
+
get_method_type(signature, false)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Resolve unknown methods by using RubyLess in the current compilation context (the
|
15
|
+
# translate method in RubyLess will call 'safe_method_type' in this module).
|
16
|
+
def r_unknown
|
17
|
+
rubyless_render(@method, @params)
|
18
|
+
rescue ::RubyLess::NoMethodError => err
|
19
|
+
parser_error("#{err.error_message} <span class='type'>#{err.method_with_arguments}</span>", err.receiver_with_class)
|
20
|
+
rescue ::RubyLess::Error => err
|
21
|
+
parser_error(err.message)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Print documentation on the current node type.
|
25
|
+
def r_m
|
26
|
+
if @params[:helper] == 'true'
|
27
|
+
klass = helper.class
|
28
|
+
else
|
29
|
+
klass = node.klass
|
30
|
+
end
|
31
|
+
|
32
|
+
out "<div class='rubyless-m'><h3>Documentation for <b>#{klass}</b></h3>"
|
33
|
+
out "<ul>"
|
34
|
+
::RubyLess::SafeClass.safe_methods_for(klass).each do |signature, opts|
|
35
|
+
opts = opts.dup
|
36
|
+
opts.delete(:method)
|
37
|
+
if opts.keys == [:class]
|
38
|
+
opts = opts[:class]
|
39
|
+
end
|
40
|
+
out "<li>#{signature.inspect} => #{opts.inspect}</li>"
|
41
|
+
end
|
42
|
+
out "</ul></div>"
|
43
|
+
end
|
44
|
+
|
45
|
+
# TEMPORARY METHOD DURING HACKING...
|
46
|
+
def r_erb
|
47
|
+
"<pre><%= @erb.gsub('<','<').gsub('>','>') %></pre>"
|
48
|
+
end
|
49
|
+
|
50
|
+
def rubyless_render(method, params)
|
51
|
+
rubyless_expand(::RubyLess.translate(method_with_arguments(method, params), self))
|
52
|
+
end
|
53
|
+
|
54
|
+
def rubyless_attr(val)
|
55
|
+
::RubyLess.translate_string(val, self)
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
def get_method_type(signature, added_options = false)
|
60
|
+
if type = node_context_from_signature(signature)
|
61
|
+
# Resolve @page, @node
|
62
|
+
type
|
63
|
+
elsif type = safe_method_from(helper, signature)
|
64
|
+
# Resolve template helper methods
|
65
|
+
type
|
66
|
+
elsif helper.respond_to?(:helpers) && type = safe_method_from(helper.helpers, signature)
|
67
|
+
# Resolve by looking at the included helpers
|
68
|
+
type
|
69
|
+
elsif node && node.klass.kind_of?(Class) && type = safe_method_from(node.klass, signature)
|
70
|
+
# Resolve node context methods (xxx.foo, xxx.bar)
|
71
|
+
type.merge(:method => "#{node.name}.#{type[:method]}")
|
72
|
+
elsif node && !added_options
|
73
|
+
# Try prepending current node before arguments: link("foo") becomse link(var1, "foo")
|
74
|
+
signature_with_node = signature.dup
|
75
|
+
signature_with_node.insert(1, node.klass)
|
76
|
+
if type = get_method_type(signature_with_node, added_options = true)
|
77
|
+
type = type.merge(:prepend_args => ::RubyLess::TypedString.new(node.name, :class => node.klass))
|
78
|
+
type
|
79
|
+
else
|
80
|
+
nil
|
81
|
+
end
|
82
|
+
else
|
83
|
+
nil
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def method_with_arguments(method, params)
|
88
|
+
hash_arguments = {}
|
89
|
+
arguments = []
|
90
|
+
keys = params.keys.map {|k| k.to_s}
|
91
|
+
keys.sort.each do |k|
|
92
|
+
if k.to_s =~ /\A_/
|
93
|
+
arguments << params[k.to_sym]
|
94
|
+
else
|
95
|
+
hash_arguments[k.to_s] = params[k.to_sym]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
arguments += [hash_arguments] if hash_arguments != {}
|
100
|
+
if arguments != [] && method[-1..-1] =~ /\w/
|
101
|
+
"#{method}(#{arguments.inspect[1..-2]})"
|
102
|
+
else
|
103
|
+
method
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def rubyless_expand(res)
|
108
|
+
if res.klass == String && @blocks.map {|b| b.kind_of?(String) ? nil : b.method}.compact.empty?
|
109
|
+
out "<%= #{res} %>"
|
110
|
+
elsif res.could_be_nil?
|
111
|
+
out "<% if #{var} = #{res} -%>"
|
112
|
+
out @markup.wrap(expand_with_node(var, res.klass))
|
113
|
+
out "<% end -%>"
|
114
|
+
else
|
115
|
+
out "<% #{var} = #{res} -%>"
|
116
|
+
out @markup.wrap(expand_with_node(var, res.klass))
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# This is used to resolve '@node' as NodeContext with class Node, '@page' as first NodeContext
|
121
|
+
# of type Page, etc.
|
122
|
+
def node_context_from_signature(signature)
|
123
|
+
return nil unless signature.size == 1
|
124
|
+
ivar = signature.first
|
125
|
+
return nil unless ivar[0..0] == '@'
|
126
|
+
begin
|
127
|
+
klass = Module.const_get(ivar[1..-1].capitalize)
|
128
|
+
context = node(klass)
|
129
|
+
rescue NameError
|
130
|
+
return nil
|
131
|
+
end
|
132
|
+
{:class => context.klass, :method => context.name}
|
133
|
+
end
|
134
|
+
|
135
|
+
def safe_method_from(context, signature)
|
136
|
+
if context.respond_to?(:safe_method_type)
|
137
|
+
context.safe_method_type(signature)
|
138
|
+
else
|
139
|
+
::RubyLess::SafeClass.safe_method_type_for(context, signature)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
end # RubyLess
|
144
|
+
end # Process
|
145
|
+
end # Zafu
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'zafu/compiler'
|
2
|
+
|
3
|
+
module Zafu
|
4
|
+
class Template
|
5
|
+
def initialize(template, src_helper = nil, compiler = Zafu::Compiler)
|
6
|
+
if template.kind_of?(String)
|
7
|
+
@ast = compiler.new(template)
|
8
|
+
else
|
9
|
+
@ast = compiler.new_with_url(template.path, :helper => src_helper)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_erb(context = {})
|
14
|
+
@ast.to_erb(context)
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_ruby(context = {})
|
18
|
+
src = ::ERB.new("<% __in_erb_template=true %>#{to_erb(context)}", nil, '-').src
|
19
|
+
|
20
|
+
# Ruby 1.9 prepends an encoding to the source. However this is
|
21
|
+
# useless because you can only set an encoding on the first line
|
22
|
+
RUBY_VERSION >= '1.9' ? src.sub(/\A#coding:.*\n/, '') : src
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'zafu/template'
|
2
|
+
|
3
|
+
module Zafu
|
4
|
+
module TestHelper
|
5
|
+
include ::RubyLess::SafeClass
|
6
|
+
|
7
|
+
def zafu_erb(source, src_helper = self, compiler = Zafu::Compiler)
|
8
|
+
Zafu::Template.new(source, src_helper, compiler).to_erb(compilation_context)
|
9
|
+
end
|
10
|
+
|
11
|
+
def zafu_render(source, src_helper = self, compiler = Zafu::Compiler)
|
12
|
+
eval Zafu::Template.new(source, src_helper, compiler).to_ruby(compilation_context)
|
13
|
+
end
|
14
|
+
|
15
|
+
def compilation_context
|
16
|
+
{:node => @node_context, :helper => self}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/zafu.rb
ADDED
data/rails/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'zafu' #File.join(File.dirname(__FILE__), '..', 'lib', 'zafu')
|
data/script/console
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# File: script/console
|
3
|
+
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
|
4
|
+
|
5
|
+
libs = " -r irb/completion"
|
6
|
+
# Perhaps use a console_lib to store any extra methods I may want available in the cosole
|
7
|
+
# libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
|
8
|
+
libs << " -r #{File.dirname(__FILE__) + '/../lib/zafu.rb'}"
|
9
|
+
puts "Loading zafu gem"
|
10
|
+
exec "#{irb} #{libs} --simple-prompt"
|
data/script/destroy
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/destroy'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
+
RubiGen::Scripts::Destroy.new.run(ARGV)
|
data/script/generate
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/generate'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
+
RubiGen::Scripts::Generate.new.run(ARGV)
|
data/test/markup_test.rb
ADDED
@@ -0,0 +1,232 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class String
|
4
|
+
def blank?
|
5
|
+
self == ''
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class NodeContextTest < Test::Unit::TestCase
|
10
|
+
include RubyLess::SafeClass
|
11
|
+
safe_method :day => {:class => String, :method => %q{Time.now.strftime('%A')}}
|
12
|
+
Markup = Zafu::Markup
|
13
|
+
|
14
|
+
context 'Parsing parameters' do
|
15
|
+
should 'retrieve values escaped with single quotes' do
|
16
|
+
h = {:class => 'worker', :style => 'tired'}
|
17
|
+
assert_equal h, Markup.parse_params("class='worker' style='tired'")
|
18
|
+
end
|
19
|
+
|
20
|
+
should 'retrieve values escaped with double quotes' do
|
21
|
+
h = {:class => 'worker', :style => 'tired'}
|
22
|
+
assert_equal h, Markup.parse_params('class="worker" style="tired"')
|
23
|
+
end
|
24
|
+
|
25
|
+
should 'retrieve values escaped with mixed quotes' do
|
26
|
+
h = {:class => 'worker', :style => 'tired'}
|
27
|
+
assert_equal h, Markup.parse_params('class=\'worker\' style="tired"')
|
28
|
+
end
|
29
|
+
|
30
|
+
should 'properly handle escaped single quotes' do
|
31
|
+
h = {:class => "that's nice", :style => 'tired'}
|
32
|
+
assert_equal h, Markup.parse_params("class='that\\\'s nice' style='tired'")
|
33
|
+
end
|
34
|
+
|
35
|
+
should 'properly handle escaped double quotes' do
|
36
|
+
h = {:class => '30"', :style => 'tired'}
|
37
|
+
assert_equal h, Markup.parse_params('class="30\\"" style="tired"')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'Setting parameters' do
|
42
|
+
setup do
|
43
|
+
@markup = Markup.new('p')
|
44
|
+
end
|
45
|
+
|
46
|
+
should 'parse params if the parameters are provided as a string' do
|
47
|
+
@markup.params = "class='shiny' id='slogan'"
|
48
|
+
h = {:class => 'shiny', :id => 'slogan'}
|
49
|
+
assert_equal h, @markup.params
|
50
|
+
end
|
51
|
+
|
52
|
+
should 'set params if the parameters are provided as a hash' do
|
53
|
+
@markup.params = {:class => 'shiny', :style => 'good'}
|
54
|
+
h = {:class => 'shiny', :style => 'good'}
|
55
|
+
assert_equal h, @markup.params
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'Stealing html params' do
|
60
|
+
setup do
|
61
|
+
@markup = Markup.new('p')
|
62
|
+
end
|
63
|
+
|
64
|
+
should 'remove common html params' do
|
65
|
+
base = {:class => 'blue', :name => 'sprout', :id => 'front_cover', :style => 'padding:5px;', :attr => 'title'}
|
66
|
+
@markup.steal_html_params_from(base)
|
67
|
+
new_base = {:name => 'sprout', :attr => 'title'}
|
68
|
+
markup_params = {:class => 'blue', :id => 'front_cover', :style => 'padding:5px;'}
|
69
|
+
assert_equal new_base, base
|
70
|
+
assert_equal markup_params, @markup.params
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'Defining the dom id' do
|
75
|
+
setup do
|
76
|
+
@markup = Markup.new('p')
|
77
|
+
@markup.params[:id] = 'foobar'
|
78
|
+
@markup.dyn_params[:id] = 'foobar'
|
79
|
+
@markup.set_id('<%= @node.zip %>')
|
80
|
+
end
|
81
|
+
|
82
|
+
should 'remove any predifined id' do
|
83
|
+
assert_nil @markup.params[:id]
|
84
|
+
end
|
85
|
+
|
86
|
+
should 'write id in the dynamic params' do
|
87
|
+
assert_equal '<%= @node.zip %>', @markup.dyn_params[:id]
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context 'Setting a dynamic param' do
|
92
|
+
setup do
|
93
|
+
@markup = Markup.new('p')
|
94
|
+
@markup.params[:foo] = 'one'
|
95
|
+
@markup.set_dyn_params(:foo => '<%= @node.two %>')
|
96
|
+
end
|
97
|
+
|
98
|
+
should 'clear a static param with same key' do
|
99
|
+
assert_nil @markup.params[:foo]
|
100
|
+
assert_equal '<%= @node.two %>', @markup.dyn_params[:foo]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
context 'Setting a static param' do
|
105
|
+
setup do
|
106
|
+
@markup = Markup.new('p')
|
107
|
+
@markup.dyn_params[:foo] = '<%= @node.two %>'
|
108
|
+
@markup.set_params(:foo => 'one')
|
109
|
+
end
|
110
|
+
|
111
|
+
should 'clear a dynamic param with same key' do
|
112
|
+
assert_nil @markup.dyn_params[:foo]
|
113
|
+
assert_equal 'one', @markup.params[:foo]
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
context 'Appending a static param' do
|
119
|
+
context 'on a static param' do
|
120
|
+
setup do
|
121
|
+
@markup = Markup.new('p')
|
122
|
+
@markup.set_params(:class => 'simple')
|
123
|
+
end
|
124
|
+
|
125
|
+
should 'append param in the static params' do
|
126
|
+
@markup.append_param(:class, 'mind')
|
127
|
+
assert_equal 'simple mind', @markup.params[:class]
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context 'on a dynamic param' do
|
132
|
+
setup do
|
133
|
+
@markup = Markup.new('p')
|
134
|
+
@markup.set_dyn_params(:class => '<%= @foo %>')
|
135
|
+
end
|
136
|
+
|
137
|
+
should 'append param in the dynamic params' do
|
138
|
+
@markup.append_param(:class, 'bar')
|
139
|
+
assert_equal '<%= @foo %> bar', @markup.dyn_params[:class]
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
context 'on an empty param' do
|
144
|
+
setup do
|
145
|
+
@markup = Markup.new('p')
|
146
|
+
end
|
147
|
+
|
148
|
+
should 'set param in the static params' do
|
149
|
+
@markup.append_param(:class, 'bar')
|
150
|
+
assert_equal 'bar', @markup.params[:class]
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context 'Appending a dynamic param' do
|
156
|
+
context 'on a static param' do
|
157
|
+
setup do
|
158
|
+
@markup = Markup.new('p')
|
159
|
+
@markup.set_params(:class => 'simple')
|
160
|
+
end
|
161
|
+
|
162
|
+
should 'copy the static param in the dynamic params' do
|
163
|
+
@markup.append_dyn_param(:class, '<%= @mind %>')
|
164
|
+
assert_equal 'simple <%= @mind %>', @markup.dyn_params[:class]
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
context 'on a dynamic param' do
|
169
|
+
setup do
|
170
|
+
@markup = Markup.new('p')
|
171
|
+
@markup.set_dyn_params(:class => '<%= @foo %>')
|
172
|
+
end
|
173
|
+
|
174
|
+
should 'append param in the dynamic params' do
|
175
|
+
@markup.append_dyn_param(:class, '<%= @bar %>')
|
176
|
+
assert_equal '<%= @foo %> <%= @bar %>', @markup.dyn_params[:class]
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
context 'on an empty param' do
|
181
|
+
setup do
|
182
|
+
@markup = Markup.new('p')
|
183
|
+
end
|
184
|
+
|
185
|
+
should 'set param in the dynamic params' do
|
186
|
+
@markup.append_dyn_param(:class, '<%= @bar %>')
|
187
|
+
assert_equal '<%= @bar %>', @markup.dyn_params[:class]
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
context 'Wrapping some text' do
|
193
|
+
setup do
|
194
|
+
@text = 'Alice: It would be so nice if something made sense for a change.'
|
195
|
+
@markup = Markup.new('p')
|
196
|
+
@markup.params = {:class => 'quote', :style => 'padding:3px; border:1px solid red;'}
|
197
|
+
end
|
198
|
+
|
199
|
+
should 'add the markup tag around the text' do
|
200
|
+
assert_equal "<p class='quote' style='padding:3px; border:1px solid red;'>#{@text}</p>", @markup.wrap(@text)
|
201
|
+
end
|
202
|
+
|
203
|
+
should 'not wrap twice if called twice' do
|
204
|
+
assert_equal "<p class='quote' style='padding:3px; border:1px solid red;'>#{@text}</p>", @markup.wrap(@markup.wrap(@text))
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
context 'Compiling params' do
|
209
|
+
setup do
|
210
|
+
@markup = Markup.new('p')
|
211
|
+
@markup.params = %q{class='one #{day}' id='foobar' name='#{day}'}
|
212
|
+
end
|
213
|
+
|
214
|
+
context 'with compile_params' do
|
215
|
+
setup do
|
216
|
+
@markup.compile_params(self)
|
217
|
+
end
|
218
|
+
|
219
|
+
should 'translate dynamic params into ERB by using RubyLess' do
|
220
|
+
assert_equal %q{<%= "one #{Time.now.strftime('%A')}" %>}, @markup.dyn_params[:class]
|
221
|
+
end
|
222
|
+
|
223
|
+
should 'translate without string on single dynamic content' do
|
224
|
+
assert_equal %q{<%= Time.now.strftime('%A') %>}, @markup.dyn_params[:name]
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
|
231
|
+
|
232
|
+
|
data/test/mock/params.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module Mock
|
2
|
+
module Params
|
3
|
+
def self.included(base)
|
4
|
+
base.before_process :filter_params
|
5
|
+
end
|
6
|
+
|
7
|
+
def filter_params
|
8
|
+
if klass = @params.delete(:class)
|
9
|
+
if klass =~ /#\{/
|
10
|
+
res = RubyLess.translate("\"#{klass}\"", self)
|
11
|
+
@markup.append_dyn_param(:class, "<%= #{res} %>")
|
12
|
+
else
|
13
|
+
@markup.append_param(:class, klass)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,190 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class NodeContextTest < Test::Unit::TestCase
|
4
|
+
class Page;end
|
5
|
+
class SubPage < Page; end
|
6
|
+
class Comment;end
|
7
|
+
NodeContext = Zafu::NodeContext
|
8
|
+
|
9
|
+
context 'In a blank context' do
|
10
|
+
setup do
|
11
|
+
@context = NodeContext.new('@node', Page)
|
12
|
+
end
|
13
|
+
|
14
|
+
should 'return the current name' do
|
15
|
+
assert_equal '@node', @context.name
|
16
|
+
end
|
17
|
+
|
18
|
+
should 'return the current class' do
|
19
|
+
assert_equal Page, @context.klass
|
20
|
+
end
|
21
|
+
|
22
|
+
should 'return true on will_be with the same class' do
|
23
|
+
assert @context.will_be?(Page)
|
24
|
+
end
|
25
|
+
|
26
|
+
should 'return false on will_be with a sub class' do
|
27
|
+
assert !@context.will_be?(SubPage)
|
28
|
+
end
|
29
|
+
|
30
|
+
should 'return false on will_be with a different class' do
|
31
|
+
assert !@context.will_be?(String)
|
32
|
+
end
|
33
|
+
|
34
|
+
should 'return self on a get for the same class' do
|
35
|
+
assert_equal @context.object_id, @context.get(Page).object_id
|
36
|
+
end
|
37
|
+
|
38
|
+
should 'return nil on a get for another class' do
|
39
|
+
assert_nil @context.get(Comment)
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'with a sub-class' do
|
43
|
+
setup do
|
44
|
+
@context = NodeContext.new('@node', SubPage)
|
45
|
+
end
|
46
|
+
|
47
|
+
should 'return true on will_be with the same class' do
|
48
|
+
assert @context.will_be?(SubPage)
|
49
|
+
end
|
50
|
+
|
51
|
+
should 'return true on will_be with a super class' do
|
52
|
+
assert @context.will_be?(Page)
|
53
|
+
end
|
54
|
+
|
55
|
+
should 'return false on will_be with a different class' do
|
56
|
+
assert !@context.will_be?(String)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'In a sub-context' do
|
62
|
+
setup do
|
63
|
+
@parent = NodeContext.new('@node', Page)
|
64
|
+
@context = @parent.move_to('comment1', Comment)
|
65
|
+
end
|
66
|
+
|
67
|
+
should 'return the current name' do
|
68
|
+
assert_equal 'comment1', @context.name
|
69
|
+
end
|
70
|
+
|
71
|
+
should 'return the current class' do
|
72
|
+
assert_equal Comment, @context.klass
|
73
|
+
end
|
74
|
+
|
75
|
+
should 'return self on a get for the same class' do
|
76
|
+
assert_equal @context.object_id, @context.get(Comment).object_id
|
77
|
+
end
|
78
|
+
|
79
|
+
should 'return the parent on a get for the class of the parent' do
|
80
|
+
assert_equal @parent.object_id, @context.get(Page).object_id
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'In a deeply nested context' do
|
85
|
+
setup do
|
86
|
+
@grandgrandma = NodeContext.new('@comment', Comment)
|
87
|
+
@grandma = @grandgrandma.move_to('page', Page)
|
88
|
+
@mother = @grandma.move_to('comment1', Comment)
|
89
|
+
@context = @mother.move_to('var1', String)
|
90
|
+
end
|
91
|
+
|
92
|
+
should 'return the current name' do
|
93
|
+
assert_equal 'var1', @context.name
|
94
|
+
end
|
95
|
+
|
96
|
+
should 'return the current class' do
|
97
|
+
assert_equal String, @context.klass
|
98
|
+
end
|
99
|
+
|
100
|
+
should 'return the first ancestor matching class on get' do
|
101
|
+
assert_equal @mother.object_id, @context.get(Comment).object_id
|
102
|
+
end
|
103
|
+
|
104
|
+
should 'return nil if no ancestor matches class on get' do
|
105
|
+
assert_nil @context.get(Fixnum)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
context 'In a sub-classes context' do
|
110
|
+
setup do
|
111
|
+
@context = NodeContext.new('super', SubPage)
|
112
|
+
end
|
113
|
+
|
114
|
+
should 'find the current context required class is an ancestor' do
|
115
|
+
assert_equal @context.object_id, @context.get(Page).object_id
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context 'In a list context' do
|
120
|
+
setup do
|
121
|
+
@context = NodeContext.new('list', [Page])
|
122
|
+
end
|
123
|
+
|
124
|
+
should 'find the context and resolve with first' do
|
125
|
+
assert context = @context.get(Page)
|
126
|
+
assert_equal 'list.first', context.name
|
127
|
+
assert_equal Page, context.klass
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context 'Generating a dom id' do
|
132
|
+
context 'in a blank context' do
|
133
|
+
setup do
|
134
|
+
@context = NodeContext.new('@foo', Page)
|
135
|
+
end
|
136
|
+
|
137
|
+
should 'return the node name in DOM id' do
|
138
|
+
assert_equal '<%= @foo.zip %>', @context.dom_id
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
context 'in a hierarchy of contexts' do
|
143
|
+
setup do
|
144
|
+
@a = NodeContext.new('@node', Page)
|
145
|
+
@b = NodeContext.new('var1', [Page], @a)
|
146
|
+
@c = NodeContext.new('var2', Page, @b)
|
147
|
+
@context = NodeContext.new('var3', Page, @c)
|
148
|
+
end
|
149
|
+
|
150
|
+
context 'with parents as dom_scopes' do
|
151
|
+
setup do
|
152
|
+
@b.dom_scope!
|
153
|
+
@c.dom_scope!
|
154
|
+
end
|
155
|
+
|
156
|
+
should 'use dom_scopes' do
|
157
|
+
assert_equal '<%= var1.zip %>_<%= var2.zip %>_<%= var3.zip %>', @context.dom_id
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
context 'with ancestors and self as dom_scopes' do
|
162
|
+
setup do
|
163
|
+
@a.dom_scope!
|
164
|
+
@context.dom_scope!
|
165
|
+
end
|
166
|
+
|
167
|
+
should 'not use self twice' do
|
168
|
+
assert_equal '<%= @node.zip %>_<%= var3.zip %>', @context.dom_id
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
context 'with a parent defining a dom_prefix' do
|
173
|
+
setup do
|
174
|
+
@b.dom_prefix = 'cart'
|
175
|
+
end
|
176
|
+
|
177
|
+
should 'use dom_prefix' do
|
178
|
+
assert_equal 'cart_<%= var3.zip %>', @context.dom_id
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
|
187
|
+
|
188
|
+
|
189
|
+
|
190
|
+
|