mab 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. data/COPYING +19 -0
  2. data/Gemfile +10 -0
  3. data/Gemfile.lock +12 -0
  4. data/README.md +224 -0
  5. data/Rakefile +8 -0
  6. data/bench.rb +37 -0
  7. data/lib/mab/mixin.rb +58 -42
  8. data/lib/mab/version.rb +1 -1
  9. data/mab-0.0.1.gem +0 -0
  10. data/mab.gemspec +20 -0
  11. data/markaby/CHANGELOG.rdoc +106 -0
  12. data/markaby/Markaby.gemspec +109 -0
  13. data/markaby/README.rdoc +317 -0
  14. data/markaby/Rakefile +78 -0
  15. data/markaby/VERSION +1 -0
  16. data/markaby/garlic.rb +29 -0
  17. data/markaby/init.rb +6 -0
  18. data/markaby/lib/markaby.rb +30 -0
  19. data/markaby/lib/markaby/builder.rb +314 -0
  20. data/markaby/lib/markaby/builder_tags.rb +64 -0
  21. data/markaby/lib/markaby/cssproxy.rb +55 -0
  22. data/markaby/lib/markaby/kernel_method.rb +7 -0
  23. data/markaby/lib/markaby/rails.rb +75 -0
  24. data/markaby/lib/markaby/rails/current.rb +85 -0
  25. data/markaby/lib/markaby/rails/deprecated.rb +124 -0
  26. data/markaby/lib/markaby/rails/rails_builder.rb +91 -0
  27. data/markaby/lib/markaby/sinatra.rb +18 -0
  28. data/markaby/lib/markaby/tags.rb +200 -0
  29. data/markaby/lib/markaby/tilt.rb +8 -0
  30. data/markaby/spec/markaby/builder_spec.rb +118 -0
  31. data/markaby/spec/markaby/css_proxy_test.rb +47 -0
  32. data/markaby/spec/markaby/fragment_test.rb +10 -0
  33. data/markaby/spec/markaby/markaby_other_static.mab +1 -0
  34. data/markaby/spec/markaby/markaby_spec.rb +184 -0
  35. data/markaby/spec/markaby/markaby_test.rb +251 -0
  36. data/markaby/spec/markaby/rails/spec_helper.rb +29 -0
  37. data/markaby/spec/markaby/rails/views/layouts/layout.mab +11 -0
  38. data/markaby/spec/markaby/rails/views/markaby/_a_partial.mab +3 -0
  39. data/markaby/spec/markaby/rails/views/markaby/_form_for_with_body_in_erb.erb +1 -0
  40. data/markaby/spec/markaby/rails/views/markaby/_partial_child_with_locals.mab +1 -0
  41. data/markaby/spec/markaby/rails/views/markaby/access_to_helpers.mab +1 -0
  42. data/markaby/spec/markaby/rails/views/markaby/broken.mab +7 -0
  43. data/markaby/spec/markaby/rails/views/markaby/commented_out_template.mab +1 -0
  44. data/markaby/spec/markaby/rails/views/markaby/correct_template_values.mab +5 -0
  45. data/markaby/spec/markaby/rails/views/markaby/double_output.mab +8 -0
  46. data/markaby/spec/markaby/rails/views/markaby/form_for.mab +2 -0
  47. data/markaby/spec/markaby/rails/views/markaby/form_for_with_fields.mab +3 -0
  48. data/markaby/spec/markaby/rails/views/markaby/form_for_with_multiple_fields.mab +4 -0
  49. data/markaby/spec/markaby/rails/views/markaby/no_values_passed.mab +3 -0
  50. data/markaby/spec/markaby/rails/views/markaby/partial_parent.mab +1 -0
  51. data/markaby/spec/markaby/rails/views/markaby/partial_parent_with_locals.mab +7 -0
  52. data/markaby/spec/markaby/rails/views/markaby/render_erb_without_explicit_render_call.erb +1 -0
  53. data/markaby/spec/markaby/rails/views/markaby/render_explicit_but_empty_markaby_layout.mab +0 -0
  54. data/markaby/spec/markaby/rails/views/markaby/render_mab_without_explicit_render_call.mab +3 -0
  55. data/markaby/spec/markaby/rails/views/markaby/render_with_ivar.mab +3 -0
  56. data/markaby/spec/markaby/rails/views/markaby/renders_erb.rhtml +1 -0
  57. data/markaby/spec/markaby/rails/views/markaby/renders_form_for_with_erb_body.mab +3 -0
  58. data/markaby/spec/markaby/rails/views/markaby/routes.mab +1 -0
  59. data/markaby/spec/markaby/rails/views/markaby/yielding.mab +3 -0
  60. data/markaby/spec/markaby/rails/views/markaby/yielding_content_for_with_block_helper.mab +5 -0
  61. data/markaby/spec/markaby/rails/views/markaby/yielding_two.mab +7 -0
  62. data/markaby/spec/markaby/rails/views/markaby/yielding_with_content_for.mab +3 -0
  63. data/markaby/spec/markaby/rails_test.rb +380 -0
  64. data/markaby/spec/markaby/rails_version_spec.rb +37 -0
  65. data/markaby/spec/markaby/sinatra/app.rb +49 -0
  66. data/markaby/spec/markaby/sinatra/sinatra_spec.rb +67 -0
  67. data/markaby/spec/markaby/sinatra/views/helpers.mab +1 -0
  68. data/markaby/spec/markaby/sinatra/views/layout.mab +7 -0
  69. data/markaby/spec/markaby/sinatra/views/markaby_template.mab +0 -0
  70. data/markaby/spec/markaby/sinatra/views/scope_instance_variables.mab +3 -0
  71. data/markaby/spec/markaby/sinatra/views/simple_html.mab +4 -0
  72. data/markaby/spec/markaby/sinatra/views/variables.mab +3 -0
  73. data/markaby/spec/markaby/tilt/erb.erb +1 -0
  74. data/markaby/spec/markaby/tilt/locals.mab +1 -0
  75. data/markaby/spec/markaby/tilt/markaby.mab +1 -0
  76. data/markaby/spec/markaby/tilt/markaby_other_static.mab +1 -0
  77. data/markaby/spec/markaby/tilt/render_twice.mab +1 -0
  78. data/markaby/spec/markaby/tilt/scope.mab +1 -0
  79. data/markaby/spec/markaby/tilt/yielding.mab +2 -0
  80. data/markaby/spec/markaby/tilt_spec.rb +75 -0
  81. data/markaby/spec/spec.opts +2 -0
  82. data/markaby/spec/spec_helper.rb +44 -0
  83. data/test/helper.rb +4 -0
  84. data/test/test_mab_builder.rb +56 -0
  85. data/test/test_mab_indentation.rb +66 -0
  86. data/test/test_mab_kernel_method.rb +10 -0
  87. data/test/test_mab_mixin.rb +246 -0
  88. metadata +92 -6
@@ -0,0 +1,18 @@
1
+ require 'markaby/tilt'
2
+ require 'sinatra'
3
+
4
+ module Sinatra
5
+ class Base
6
+ # sinatra's #render looks for options in Sinatra::Application
7
+ # by asking if it responds_to?(:mab)
8
+ # Unfortunately, if the the mab kernel method is included,
9
+ # Sinatra::Application will respond_to? it.
10
+ set :mab, {}
11
+ end
12
+
13
+ module Templates
14
+ def mab(template, options={}, locals={})
15
+ render :mab, template, options, locals
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,200 @@
1
+ module Markaby
2
+ FORM_TAGS = [ :form, :input, :select, :textarea ]
3
+ SELF_CLOSING_TAGS = [ :base, :meta, :link, :hr, :br, :param, :img, :area, :input, :col, :frame ]
4
+
5
+ # Common sets of attributes.
6
+ AttrCore = [:id, :class, :style, :title]
7
+ AttrI18n = [:lang, 'xml:lang'.intern, :dir]
8
+ AttrEvents = [:onclick,
9
+ :ondblclick,
10
+ :onmousedown,
11
+ :onmouseup,
12
+ :onmouseover,
13
+ :onmousemove,
14
+ :onmouseout,
15
+ :onkeypress,
16
+ :onkeydown,
17
+ :onkeyup]
18
+ AttrFocus = [:accesskey, :tabindex, :onfocus, :onblur]
19
+ AttrHAlign = [:align, :char, :charoff]
20
+ AttrVAlign = [:valign]
21
+ Attrs = AttrCore + AttrI18n + AttrEvents
22
+
23
+ AttrsBoolean = [
24
+ :checked, :disabled, :multiple, :readonly, :selected, # standard forms
25
+ :autofocus, :required, :novalidate, :formnovalidate, # HTML5 forms
26
+ :defer, :ismap, # <script defer>, <img ismap>
27
+ :compact, :declare, :noresize, :noshade, :nowrap # deprecated or unused
28
+ ]
29
+
30
+ # All the tags and attributes from XHTML 1.0 Strict
31
+ class XHTMLStrict
32
+ class << self
33
+ attr_accessor :tags, :tagset, :forms, :self_closing, :doctype
34
+ end
35
+
36
+ @doctype = ['-//W3C//DTD XHTML 1.0 Strict//EN', 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd']
37
+ @tagset = {
38
+ :html => AttrI18n + [:id, :xmlns],
39
+ :head => AttrI18n + [:id, :profile],
40
+ :title => AttrI18n + [:id],
41
+ :base => [:href, :id],
42
+ :meta => AttrI18n + [:id, :http, :name, :content, :scheme, 'http-equiv'.intern],
43
+ :link => Attrs + [:charset, :href, :hreflang, :type, :rel, :rev, :media],
44
+ :style => AttrI18n + [:id, :type, :media, :title, 'xml:space'.intern],
45
+ :script => [:id, :charset, :type, :src, :defer, 'xml:space'.intern],
46
+ :noscript => Attrs,
47
+ :body => Attrs + [:onload, :onunload],
48
+ :div => Attrs,
49
+ :p => Attrs,
50
+ :ul => Attrs,
51
+ :ol => Attrs,
52
+ :li => Attrs,
53
+ :dl => Attrs,
54
+ :dt => Attrs,
55
+ :dd => Attrs,
56
+ :address => Attrs,
57
+ :hr => Attrs,
58
+ :pre => Attrs + ['xml:space'.intern],
59
+ :blockquote => Attrs + [:cite],
60
+ :ins => Attrs + [:cite, :datetime],
61
+ :del => Attrs + [:cite, :datetime],
62
+ :a => Attrs + AttrFocus + [:charset, :type, :name, :href, :hreflang, :rel, :rev, :shape, :coords],
63
+ :span => Attrs,
64
+ :bdo => AttrCore + AttrEvents + [:lang, 'xml:lang'.intern, :dir],
65
+ :br => AttrCore,
66
+ :em => Attrs,
67
+ :strong => Attrs,
68
+ :dfn => Attrs,
69
+ :code => Attrs,
70
+ :samp => Attrs,
71
+ :kbd => Attrs,
72
+ :var => Attrs,
73
+ :cite => Attrs,
74
+ :abbr => Attrs,
75
+ :acronym => Attrs,
76
+ :q => Attrs + [:cite],
77
+ :sub => Attrs,
78
+ :sup => Attrs,
79
+ :tt => Attrs,
80
+ :i => Attrs,
81
+ :b => Attrs,
82
+ :big => Attrs,
83
+ :small => Attrs,
84
+ :object => Attrs + [:declare, :classid, :codebase, :data, :type, :codetype, :archive, :standby, :height, :width, :usemap, :name, :tabindex],
85
+ :param => [:id, :name, :value, :valuetype, :type],
86
+ :img => Attrs + [:src, :alt, :longdesc, :height, :width, :usemap, :ismap],
87
+ :map => AttrI18n + AttrEvents + [:id, :class, :style, :title, :name],
88
+ :area => Attrs + AttrFocus + [:shape, :coords, :href, :nohref, :alt],
89
+ :form => Attrs + [:action, :method, :enctype, :onsubmit, :onreset, :accept, :accept],
90
+ :label => Attrs + [:for, :accesskey, :onfocus, :onblur],
91
+ :input => Attrs + AttrFocus + [:type, :name, :value, :checked, :disabled, :readonly, :size, :maxlength, :src, :alt, :usemap, :onselect, :onchange, :accept],
92
+ :select => Attrs + [:name, :size, :multiple, :disabled, :tabindex, :onfocus, :onblur, :onchange],
93
+ :optgroup => Attrs + [:disabled, :label],
94
+ :option => Attrs + [:selected, :disabled, :label, :value],
95
+ :textarea => Attrs + AttrFocus + [:name, :rows, :cols, :disabled, :readonly, :onselect, :onchange],
96
+ :fieldset => Attrs,
97
+ :legend => Attrs + [:accesskey],
98
+ :button => Attrs + AttrFocus + [:name, :value, :type, :disabled],
99
+ :table => Attrs + [:summary, :width, :border, :frame, :rules, :cellspacing, :cellpadding],
100
+ :caption => Attrs,
101
+ :colgroup => Attrs + AttrHAlign + AttrVAlign + [:span, :width],
102
+ :col => Attrs + AttrHAlign + AttrVAlign + [:span, :width],
103
+ :thead => Attrs + AttrHAlign + AttrVAlign,
104
+ :tfoot => Attrs + AttrHAlign + AttrVAlign,
105
+ :tbody => Attrs + AttrHAlign + AttrVAlign,
106
+ :tr => Attrs + AttrHAlign + AttrVAlign,
107
+ :th => Attrs + AttrHAlign + AttrVAlign + [:abbr, :axis, :headers, :scope, :rowspan, :colspan],
108
+ :td => Attrs + AttrHAlign + AttrVAlign + [:abbr, :axis, :headers, :scope, :rowspan, :colspan],
109
+ :h1 => Attrs,
110
+ :h2 => Attrs,
111
+ :h3 => Attrs,
112
+ :h4 => Attrs,
113
+ :h5 => Attrs,
114
+ :h6 => Attrs
115
+ }
116
+
117
+ @tags = @tagset.keys
118
+ @forms = @tags & FORM_TAGS
119
+ @self_closing = @tags & SELF_CLOSING_TAGS
120
+ end
121
+
122
+ # Additional tags found in XHTML 1.0 Transitional
123
+ class XHTMLTransitional
124
+ class << self
125
+ attr_accessor :tags, :tagset, :forms, :self_closing, :doctype
126
+ end
127
+
128
+ @doctype = ['-//W3C//DTD XHTML 1.0 Transitional//EN', 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd']
129
+ @tagset = XHTMLStrict.tagset.merge({
130
+ :strike => Attrs,
131
+ :center => Attrs,
132
+ :dir => Attrs + [:compact],
133
+ :noframes => Attrs,
134
+ :basefont => [:id, :size, :color, :face],
135
+ :u => Attrs,
136
+ :menu => Attrs + [:compact],
137
+ :iframe => AttrCore + [:longdesc, :name, :src, :frameborder, :marginwidth, :marginheight, :scrolling, :align, :height, :width],
138
+ :font => AttrCore + AttrI18n + [:size, :color, :face],
139
+ :s => Attrs,
140
+ :applet => AttrCore + [:codebase, :archive, :code, :object, :alt, :name, :width, :height, :align, :hspace, :vspace],
141
+ :isindex => AttrCore + AttrI18n + [:prompt]
142
+ })
143
+
144
+ # Additional attributes found in XHTML 1.0 Transitional
145
+ additional_tags = {
146
+ :script => [:language],
147
+ :a => [:target],
148
+ :td => [:bgcolor, :nowrap, :width, :height],
149
+ :p => [:align],
150
+ :h5 => [:align],
151
+ :h3 => [:align],
152
+ :li => [:type, :value],
153
+ :div => [:align],
154
+ :pre => [:width],
155
+ :body => [:background, :bgcolor, :text, :link, :vlink, :alink],
156
+ :ol => [:type, :compact, :start],
157
+ :h4 => [:align],
158
+ :h2 => [:align],
159
+ :object => [:align, :border, :hspace, :vspace],
160
+ :img => [:name, :align, :border, :hspace, :vspace],
161
+ :link => [:target],
162
+ :legend => [:align],
163
+ :dl => [:compact],
164
+ :input => [:align],
165
+ :h6 => [:align],
166
+ :hr => [:align, :noshade, :size, :width],
167
+ :base => [:target],
168
+ :ul => [:type, :compact],
169
+ :br => [:clear],
170
+ :form => [:name, :target],
171
+ :area => [:target],
172
+ :h1 => [:align]
173
+ }
174
+
175
+ additional_tags.each do |k, v|
176
+ @tagset[k] += v
177
+ end
178
+
179
+ @tags = @tagset.keys
180
+ @forms = @tags & FORM_TAGS
181
+ @self_closing = @tags & SELF_CLOSING_TAGS
182
+ end
183
+
184
+ # Additional tags found in XHTML 1.0 Frameset
185
+ class XHTMLFrameset
186
+ class << self
187
+ attr_accessor :tags, :tagset, :forms, :self_closing, :doctype
188
+ end
189
+
190
+ @doctype = ['-//W3C//DTD XHTML 1.0 Frameset//EN', 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd']
191
+ @tagset = XHTMLTransitional.tagset.merge({
192
+ :frameset => AttrCore + [:rows, :cols, :onload, :onunload],
193
+ :frame => AttrCore + [:longdesc, :name, :src, :frameborder, :marginwidth, :marginheight, :noresize, :scrolling]
194
+ })
195
+
196
+ @tags = @tagset.keys
197
+ @forms = @tags & FORM_TAGS
198
+ @self_closing = @tags & SELF_CLOSING_TAGS
199
+ end
200
+ end
@@ -0,0 +1,8 @@
1
+ require 'markaby'
2
+ require 'tilt'
3
+
4
+ module Markaby
5
+ module Tilt
6
+ Template = ::Tilt::MarkabyTemplate
7
+ end
8
+ end
@@ -0,0 +1,118 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ module Markaby
4
+ describe Builder do
5
+ before do
6
+ Markaby::Builder.restore_defaults!
7
+ end
8
+
9
+ after do
10
+ Markaby::Builder.restore_defaults!
11
+ end
12
+
13
+ it "should have method missing as a private method" do
14
+ private_methods = Markaby::Builder.private_instance_methods.dup
15
+ private_methods.map! { |m| m.to_sym }
16
+ private_methods.should include(:method_missing)
17
+ end
18
+
19
+ describe "setting options" do
20
+ it "should be able to restore defaults after setting" do
21
+ Markaby::Builder.set :indent, 2
22
+ Markaby::Builder.restore_defaults!
23
+
24
+ Markaby::Builder.get(:indent).should == 0
25
+ end
26
+
27
+ it "should be able to set global options" do
28
+ Markaby::Builder.set :indent, 2
29
+ Markaby::Builder.get(:indent).should == 2
30
+ end
31
+ end
32
+
33
+ describe "hidden internal variables" do
34
+ # internal clobbering by passed in assigns
35
+ it "should not overwrite internal helpers ivar when assigning a :helpers key" do
36
+ helper = Class.new do
37
+ def some_method
38
+ "a value"
39
+ end
40
+ end.new
41
+
42
+ builder = Markaby::Builder.new({:helpers => nil}, helper)
43
+ builder.some_method.should == "a value"
44
+ end
45
+ end
46
+
47
+ describe "evaluating blocks" do
48
+ it "should evaluate a pure-string block (without requiring a call to the text method)" do
49
+ b = Builder.new do
50
+ "foo"
51
+ end
52
+
53
+ b.to_s.should == "foo"
54
+ end
55
+
56
+ it "should only evaluate the last argument in a pure-string block" do
57
+ b = Builder.new do
58
+ "foo"
59
+ "bar"
60
+ end
61
+
62
+ b.to_s.should == "bar"
63
+ end
64
+
65
+ it "should evaluate pure-strings inside an tag" do
66
+ b = Builder.new do
67
+ h1 do
68
+ "foo"
69
+ end
70
+ end
71
+
72
+ b.to_s.should == "<h1>foo</h1>"
73
+ end
74
+
75
+ it "should ignore a pure string in the block, even if comes last, if there has been any markup whatsoever" do
76
+ b = Builder.new do
77
+ h1
78
+ "foo"
79
+ end
80
+
81
+ b.to_s.should == "<h1/>"
82
+ end
83
+ end
84
+
85
+ describe "capture" do
86
+ before do
87
+ @builder = Builder.new
88
+ end
89
+
90
+ it "should return the string captured" do
91
+ out = @builder.capture do
92
+ h1 "TEST"
93
+ h2 "CAPTURE ME"
94
+ end
95
+
96
+ out.should == "<h1>TEST</h1><h2>CAPTURE ME</h2>"
97
+ end
98
+
99
+ it "should not change the output buffer" do
100
+ lambda {
101
+ @builder.capture do
102
+ h1 "FOO!"
103
+ end
104
+ }.should_not change { @builder.to_s }
105
+ end
106
+
107
+ it "should be able to capture inside a capture" do
108
+ out = @builder.capture do
109
+ capture do
110
+ h1 "foo"
111
+ end
112
+ end
113
+
114
+ out.should == "<h1>foo</h1>"
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,47 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ class CssProxyTest < Test::Unit::TestCase
4
+ it "should have method_missing as private" do
5
+ methods = Markaby::CssProxy.private_instance_methods.dup
6
+ methods.map! { |m| m.to_sym }
7
+
8
+ methods.should include(:method_missing)
9
+ end
10
+
11
+ def mock_builder
12
+ mock_builder = Class.new do
13
+ def tag!(*args); end
14
+ end.new
15
+ end
16
+
17
+ def test_responds_to_everything
18
+ proxy = Markaby::CssProxy.new(mock_builder, 'stream', :sym)
19
+
20
+ assert proxy.respond_to?(:any_method)
21
+ assert proxy.respond_to?(:foobarbazasdfasdfadfs)
22
+ end
23
+
24
+ def test_does_not_respond_to_method_missing
25
+ proxy = Markaby::CssProxy.new(mock_builder, 'stream', :sym)
26
+
27
+ assert !proxy.respond_to?(:method_missing)
28
+ end
29
+
30
+ def test_does_respond_to_private_instance_methods_with_private_flag_set_to_true
31
+ proxy = Markaby::CssProxy.new(mock_builder, 'stream', :sym)
32
+
33
+ assert proxy.respond_to?(:method_missing, true)
34
+ end
35
+
36
+ def test_does_not_respond_to_private_instance_methods_with_private_flag_set_to_false
37
+ proxy = Markaby::CssProxy.new(mock_builder, 'stream', :sym)
38
+
39
+ assert !proxy.respond_to?(:method_missing, false)
40
+ end
41
+
42
+ def test_respond_to_should_always_return_boolean
43
+ proxy = Markaby::CssProxy.new(mock_builder, 'stream', :sym)
44
+
45
+ assert_equal proxy.respond_to?(:method_missing, :a_value), true
46
+ end
47
+ end
@@ -0,0 +1,10 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ class FragmentTest < Test::Unit::TestCase
4
+ it "should have method_missing as a private instance method" do
5
+ private_methods = Markaby::Fragment.private_instance_methods.dup
6
+ private_methods.map! { |m| m.to_sym }
7
+
8
+ private_methods.should include(:method_missing)
9
+ end
10
+ end
@@ -0,0 +1 @@
1
+ text "_why?"
@@ -0,0 +1,184 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe Markaby do
4
+ it "can assign helpers after instantiation" do
5
+ helper = mock 'helper', :foo => :bar
6
+
7
+ builder = Markaby::Builder.new
8
+ builder.helper = helper
9
+ builder.foo.should == :bar
10
+ end
11
+
12
+ it "should be able to set a local" do
13
+ builder = Markaby::Builder.new
14
+ builder.locals = { :foo => "bar" }
15
+ builder.foo.should == "bar"
16
+ end
17
+
18
+ it "should be able to set a different local value" do
19
+ builder = Markaby::Builder.new
20
+ builder.locals = { :foo => "baz" }
21
+ builder.foo.should == "baz"
22
+ end
23
+
24
+ it "should assign the correct key" do
25
+ builder = Markaby::Builder.new
26
+ builder.locals = { :key => :value }
27
+ builder.key.should == :value
28
+ end
29
+
30
+ it "should be able to assign multiple locals" do
31
+ builder = Markaby::Builder.new
32
+
33
+ builder.locals = { :one => "two", :three => "four" }
34
+
35
+ builder.one.should == "two"
36
+ builder.three.should == "four"
37
+ end
38
+
39
+ def test_builder_bang_methods
40
+ assert_equal "<?xml version=\"1.0\" encoding=\"UTF-8\"?>", mab { instruct! }
41
+ end
42
+
43
+ it "should be able to produce the correct html from a fragment" do
44
+ str = ""
45
+ str += "<div>"
46
+ str += "<h1>Monkeys</h1>"
47
+ str += "<h2>Giraffes <small>Miniature</small> and <strong>Large</strong></h2>"
48
+ str += "<h3>Donkeys</h3>"
49
+ str += "<h4>Parakeet <b><i>Innocent IV</i></b> in Classic Chartreuse</h4>"
50
+ str += "</div>"
51
+
52
+ generated = mab {
53
+ div {
54
+ h1 "Monkeys"
55
+ h2 {
56
+ "Giraffes #{small('Miniature')} and #{strong 'Large'}"
57
+ }
58
+ h3 "Donkeys"
59
+ h4 { "Parakeet #{b { i 'Innocent IV' }} in Classic Chartreuse" }
60
+ }
61
+ }
62
+
63
+ generated.should == str
64
+ end
65
+
66
+ def test_fragments
67
+ assert_equal %{<div><h1>Monkeys</h1><h2>Giraffes <strong>Miniature</strong></h2><h3>Donkeys</h3></div>},
68
+ mab { div { h1 "Monkeys"; h2 { "Giraffes #{strong 'Miniature' }" }; h3 "Donkeys" } }
69
+
70
+ assert_equal %{<div><h1>Monkeys</h1><h2>Giraffes <small>Miniature</small> and <strong>Large</strong></h2><h3>Donkeys</h3><h4>Parakeet <strong>Large</strong> as well...</h4></div>},
71
+ mab { div { @a = small 'Miniature'; @b = strong 'Large'; h1 "Monkeys"; h2 { "Giraffes #{@a} and #{@b}" }; h3 "Donkeys"; h4 { "Parakeet #{@b} as well..." } } }
72
+ end
73
+
74
+ def test_invalid_xhtml
75
+ assert_exception(NoMethodError, "undefined method `dav'") { dav {} }
76
+ assert_exception(Markaby::InvalidXhtmlError, "no attribute `styl' on div elements") { div(:styl => 'ok') {} }
77
+ assert_exception(Markaby::InvalidXhtmlError, "no attribute `class' on tbody elements") { tbody.okay {} }
78
+ end
79
+
80
+ def test_full_doc_transitional
81
+ doc = mab { xhtml_transitional { head { title 'OKay' } } }
82
+ assert doc =~ /^<\?xml version="1.0" encoding="UTF-8"\?>/
83
+ assert doc.include?(%{"-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">})
84
+ assert doc.include?(%{<title>OKay</title>})
85
+ end
86
+
87
+ def test_full_doc_strict
88
+ doc = mab { xhtml_strict { head { title 'OKay' } } }
89
+ assert doc =~ /^<\?xml version="1.0" encoding="UTF-8"\?>/
90
+ assert doc.include?(%{"-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">})
91
+ assert doc.include?(%{<title>OKay</title>})
92
+ end
93
+
94
+ def test_full_doc_frameset
95
+ doc = mab { xhtml_frameset { head { title 'OKay' } } }
96
+ assert doc =~ /^<\?xml version="1.0" encoding="UTF-8"\?>/
97
+ assert doc.include?(%{"-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">})
98
+ assert doc.include?(%{<title>OKay</title>})
99
+ end
100
+
101
+ def test_root_attributes_can_be_changed
102
+ doc = mab { xhtml_strict(:lang => 'fr') { head { title { 'Salut!' } } } }
103
+ assert doc.include?(%{"-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">})
104
+ assert doc.include?(%{<title>Salut!</title>})
105
+ assert doc.include?(%{ lang="fr"})
106
+ end
107
+
108
+ def version_file
109
+ File.expand_path(File.dirname(__FILE__) + "/../../VERSION")
110
+ end
111
+
112
+ def test_markaby_should_have_correct_version
113
+ assert_equal Markaby::VERSION, File.read(version_file).strip
114
+ end
115
+
116
+ def test_duplicate_usage_of_same_id
117
+ assert_raises Markaby::InvalidXhtmlError do
118
+ mab do
119
+ p.one!
120
+ p.one!
121
+ end
122
+ end
123
+ end
124
+
125
+ # auto validation
126
+
127
+ def test_tagging_with_invalid_tag_should_raise_error
128
+ assert_raises Markaby::InvalidXhtmlError do
129
+ mab do
130
+ tag! :an_invalid_tag
131
+ end
132
+ end
133
+ end
134
+
135
+ def test_self_closing_html_tag_with_block_throws_errors
136
+ assert_raises Markaby::InvalidXhtmlError do
137
+ mab do
138
+ html_tag :img do
139
+ end
140
+ end
141
+ end
142
+ end
143
+
144
+ def test_local_assigning
145
+ builder = Markaby::Builder.new(:variable => :a_value)
146
+
147
+ assert_equal :a_value, builder.variable
148
+ end
149
+
150
+ def test_local_assignment_with_strings
151
+ builder = Markaby::Builder.new("variable" => :a_value)
152
+ assert_equal :a_value, builder.variable
153
+ end
154
+
155
+ def test_local_assignment_prefers_symbols_to_strings
156
+ builder = Markaby::Builder.new("variable" => "string_value", :variable => :symbol_value)
157
+ assert_equal :symbol_value, builder.variable
158
+ end
159
+
160
+ def test_method_missing_should_call_tag_if_no_tagset_present
161
+ Markaby::Builder.set(:tagset, nil)
162
+
163
+ builder = Markaby::Builder.new
164
+ builder.something.should == "<something/>"
165
+ end
166
+
167
+ it "should copy instance variables from a helper object" do
168
+ klass = Class.new do
169
+ def initialize
170
+ @hello = "hello there"
171
+ end
172
+ end
173
+
174
+ builder = Markaby::Builder.new({}, klass.new)
175
+ builder.capture { @hello }.should == "hello there"
176
+ end
177
+
178
+ describe Markaby::InvalidXhtmlError do
179
+ it "should inherit from StandardError" do
180
+ Markaby::InvalidXhtmlError.superclass.should == StandardError
181
+ end
182
+ end
183
+ end
184
+