Markaby 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/.gitignore +4 -0
  2. data/CHANGELOG.rdoc +43 -0
  3. data/Markaby.gemspec +100 -0
  4. data/README.rdoc +262 -0
  5. data/Rakefile +48 -0
  6. data/VERSION +1 -0
  7. data/garlic.rb +29 -0
  8. data/init.rb +6 -0
  9. data/lib/markaby/builder.rb +275 -0
  10. data/lib/markaby/builder_tags.rb +64 -0
  11. data/lib/markaby/cssproxy.rb +55 -0
  12. data/lib/markaby/kernel_method.rb +7 -0
  13. data/lib/markaby/rails/current.rb +41 -0
  14. data/lib/markaby/rails/deprecated.rb +122 -0
  15. data/lib/markaby/rails.rb +68 -0
  16. data/lib/markaby/tags.rb +193 -0
  17. data/lib/markaby/tilt.rb +21 -0
  18. data/lib/markaby.rb +30 -0
  19. data/spec/markaby/builder_spec.rb +40 -0
  20. data/spec/markaby/css_proxy_spec.rb +44 -0
  21. data/spec/markaby/fragment_spec.rb +7 -0
  22. data/spec/markaby/markaby_other_static.mab +1 -0
  23. data/spec/markaby/markaby_spec.rb +207 -0
  24. data/spec/markaby/rails/spec_helper.rb +20 -0
  25. data/spec/markaby/rails/views/markaby/_a_partial.mab +3 -0
  26. data/spec/markaby/rails/views/markaby/_partial_child_with_locals.mab +1 -0
  27. data/spec/markaby/rails/views/markaby/access_to_helpers.mab +1 -0
  28. data/spec/markaby/rails/views/markaby/broken.mab +7 -0
  29. data/spec/markaby/rails/views/markaby/correct_template_values.mab +5 -0
  30. data/spec/markaby/rails/views/markaby/no_values_passed.mab +3 -0
  31. data/spec/markaby/rails/views/markaby/partial_parent.mab +1 -0
  32. data/spec/markaby/rails/views/markaby/partial_parent_with_locals.mab +7 -0
  33. data/spec/markaby/rails/views/markaby/render_erb_without_explicit_render_call.erb +1 -0
  34. data/spec/markaby/rails/views/markaby/render_explicit_but_empty_markaby_layout.mab +0 -0
  35. data/spec/markaby/rails/views/markaby/render_mab_without_explicit_render_call.mab +3 -0
  36. data/spec/markaby/rails/views/markaby/render_with_ivar.mab +3 -0
  37. data/spec/markaby/rails/views/markaby/renders_erb.rhtml +1 -0
  38. data/spec/markaby/rails_spec.rb +190 -0
  39. data/spec/markaby/rails_version_spec.rb +37 -0
  40. data/spec/markaby/tilt/erb.erb +1 -0
  41. data/spec/markaby/tilt/locals.mab +1 -0
  42. data/spec/markaby/tilt/markaby.mab +1 -0
  43. data/spec/markaby/tilt/markaby_other_static.mab +1 -0
  44. data/spec/markaby/tilt/render_twice.mab +1 -0
  45. data/spec/markaby/tilt/scope.mab +1 -0
  46. data/spec/markaby/tilt/yielding.mab +2 -0
  47. data/spec/markaby/tilt_spec.rb +86 -0
  48. data/spec/markaby/xml_markup_spec.rb +9 -0
  49. data/spec/spec.opts +2 -0
  50. data/spec/spec_helper.rb +39 -0
  51. metadata +126 -0
@@ -0,0 +1,193 @@
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
+ # All the tags and attributes from XHTML 1.0 Strict
24
+ class XHTMLStrict
25
+ class << self
26
+ attr_accessor :tags, :tagset, :forms, :self_closing, :doctype
27
+ end
28
+
29
+ @doctype = ['-//W3C//DTD XHTML 1.0 Strict//EN', 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd']
30
+ @tagset = {
31
+ :html => AttrI18n + [:id, :xmlns],
32
+ :head => AttrI18n + [:id, :profile],
33
+ :title => AttrI18n + [:id],
34
+ :base => [:href, :id],
35
+ :meta => AttrI18n + [:id, :http, :name, :content, :scheme, 'http-equiv'.intern],
36
+ :link => Attrs + [:charset, :href, :hreflang, :type, :rel, :rev, :media],
37
+ :style => AttrI18n + [:id, :type, :media, :title, 'xml:space'.intern],
38
+ :script => [:id, :charset, :type, :src, :defer, 'xml:space'.intern],
39
+ :noscript => Attrs,
40
+ :body => Attrs + [:onload, :onunload],
41
+ :div => Attrs,
42
+ :p => Attrs,
43
+ :ul => Attrs,
44
+ :ol => Attrs,
45
+ :li => Attrs,
46
+ :dl => Attrs,
47
+ :dt => Attrs,
48
+ :dd => Attrs,
49
+ :address => Attrs,
50
+ :hr => Attrs,
51
+ :pre => Attrs + ['xml:space'.intern],
52
+ :blockquote => Attrs + [:cite],
53
+ :ins => Attrs + [:cite, :datetime],
54
+ :del => Attrs + [:cite, :datetime],
55
+ :a => Attrs + AttrFocus + [:charset, :type, :name, :href, :hreflang, :rel, :rev, :shape, :coords],
56
+ :span => Attrs,
57
+ :bdo => AttrCore + AttrEvents + [:lang, 'xml:lang'.intern, :dir],
58
+ :br => AttrCore,
59
+ :em => Attrs,
60
+ :strong => Attrs,
61
+ :dfn => Attrs,
62
+ :code => Attrs,
63
+ :samp => Attrs,
64
+ :kbd => Attrs,
65
+ :var => Attrs,
66
+ :cite => Attrs,
67
+ :abbr => Attrs,
68
+ :acronym => Attrs,
69
+ :q => Attrs + [:cite],
70
+ :sub => Attrs,
71
+ :sup => Attrs,
72
+ :tt => Attrs,
73
+ :i => Attrs,
74
+ :b => Attrs,
75
+ :big => Attrs,
76
+ :small => Attrs,
77
+ :object => Attrs + [:declare, :classid, :codebase, :data, :type, :codetype, :archive, :standby, :height, :width, :usemap, :name, :tabindex],
78
+ :param => [:id, :name, :value, :valuetype, :type],
79
+ :img => Attrs + [:src, :alt, :longdesc, :height, :width, :usemap, :ismap],
80
+ :map => AttrI18n + AttrEvents + [:id, :class, :style, :title, :name],
81
+ :area => Attrs + AttrFocus + [:shape, :coords, :href, :nohref, :alt],
82
+ :form => Attrs + [:action, :method, :enctype, :onsubmit, :onreset, :accept, :accept],
83
+ :label => Attrs + [:for, :accesskey, :onfocus, :onblur],
84
+ :input => Attrs + AttrFocus + [:type, :name, :value, :checked, :disabled, :readonly, :size, :maxlength, :src, :alt, :usemap, :onselect, :onchange, :accept],
85
+ :select => Attrs + [:name, :size, :multiple, :disabled, :tabindex, :onfocus, :onblur, :onchange],
86
+ :optgroup => Attrs + [:disabled, :label],
87
+ :option => Attrs + [:selected, :disabled, :label, :value],
88
+ :textarea => Attrs + AttrFocus + [:name, :rows, :cols, :disabled, :readonly, :onselect, :onchange],
89
+ :fieldset => Attrs,
90
+ :legend => Attrs + [:accesskey],
91
+ :button => Attrs + AttrFocus + [:name, :value, :type, :disabled],
92
+ :table => Attrs + [:summary, :width, :border, :frame, :rules, :cellspacing, :cellpadding],
93
+ :caption => Attrs,
94
+ :colgroup => Attrs + AttrHAlign + AttrVAlign + [:span, :width],
95
+ :col => Attrs + AttrHAlign + AttrVAlign + [:span, :width],
96
+ :thead => Attrs + AttrHAlign + AttrVAlign,
97
+ :tfoot => Attrs + AttrHAlign + AttrVAlign,
98
+ :tbody => Attrs + AttrHAlign + AttrVAlign,
99
+ :tr => Attrs + AttrHAlign + AttrVAlign,
100
+ :th => Attrs + AttrHAlign + AttrVAlign + [:abbr, :axis, :headers, :scope, :rowspan, :colspan],
101
+ :td => Attrs + AttrHAlign + AttrVAlign + [:abbr, :axis, :headers, :scope, :rowspan, :colspan],
102
+ :h1 => Attrs,
103
+ :h2 => Attrs,
104
+ :h3 => Attrs,
105
+ :h4 => Attrs,
106
+ :h5 => Attrs,
107
+ :h6 => Attrs
108
+ }
109
+
110
+ @tags = @tagset.keys
111
+ @forms = @tags & FORM_TAGS
112
+ @self_closing = @tags & SELF_CLOSING_TAGS
113
+ end
114
+
115
+ # Additional tags found in XHTML 1.0 Transitional
116
+ class XHTMLTransitional
117
+ class << self
118
+ attr_accessor :tags, :tagset, :forms, :self_closing, :doctype
119
+ end
120
+
121
+ @doctype = ['-//W3C//DTD XHTML 1.0 Transitional//EN', 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd']
122
+ @tagset = XHTMLStrict.tagset.merge({
123
+ :strike => Attrs,
124
+ :center => Attrs,
125
+ :dir => Attrs + [:compact],
126
+ :noframes => Attrs,
127
+ :basefont => [:id, :size, :color, :face],
128
+ :u => Attrs,
129
+ :menu => Attrs + [:compact],
130
+ :iframe => AttrCore + [:longdesc, :name, :src, :frameborder, :marginwidth, :marginheight, :scrolling, :align, :height, :width],
131
+ :font => AttrCore + AttrI18n + [:size, :color, :face],
132
+ :s => Attrs,
133
+ :applet => AttrCore + [:codebase, :archive, :code, :object, :alt, :name, :width, :height, :align, :hspace, :vspace],
134
+ :isindex => AttrCore + AttrI18n + [:prompt]
135
+ })
136
+
137
+ # Additional attributes found in XHTML 1.0 Transitional
138
+ additional_tags = {
139
+ :script => [:language],
140
+ :a => [:target],
141
+ :td => [:bgcolor, :nowrap, :width, :height],
142
+ :p => [:align],
143
+ :h5 => [:align],
144
+ :h3 => [:align],
145
+ :li => [:type, :value],
146
+ :div => [:align],
147
+ :pre => [:width],
148
+ :body => [:background, :bgcolor, :text, :link, :vlink, :alink],
149
+ :ol => [:type, :compact, :start],
150
+ :h4 => [:align],
151
+ :h2 => [:align],
152
+ :object => [:align, :border, :hspace, :vspace],
153
+ :img => [:name, :align, :border, :hspace, :vspace],
154
+ :link => [:target],
155
+ :legend => [:align],
156
+ :dl => [:compact],
157
+ :input => [:align],
158
+ :h6 => [:align],
159
+ :hr => [:align, :noshade, :size, :width],
160
+ :base => [:target],
161
+ :ul => [:type, :compact],
162
+ :br => [:clear],
163
+ :form => [:name, :target],
164
+ :area => [:target],
165
+ :h1 => [:align]
166
+ }
167
+
168
+ additional_tags.each do |k, v|
169
+ @tagset[k] += v
170
+ end
171
+
172
+ @tags = @tagset.keys
173
+ @forms = @tags & FORM_TAGS
174
+ @self_closing = @tags & SELF_CLOSING_TAGS
175
+ end
176
+
177
+ # Additional tags found in XHTML 1.0 Frameset
178
+ class XHTMLFrameset
179
+ class << self
180
+ attr_accessor :tags, :tagset, :forms, :self_closing, :doctype
181
+ end
182
+
183
+ @doctype = ['-//W3C//DTD XHTML 1.0 Frameset//EN', 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd']
184
+ @tagset = XHTMLTransitional.tagset.merge({
185
+ :frameset => AttrCore + [:rows, :cols, :onload, :onunload],
186
+ :frame => AttrCore + [:longdesc, :name, :src, :frameborder, :marginwidth, :marginheight, :noresize, :scrolling]
187
+ })
188
+
189
+ @tags = @tagset.keys
190
+ @forms = @tags & FORM_TAGS
191
+ @self_closing = @tags & SELF_CLOSING_TAGS
192
+ end
193
+ end
@@ -0,0 +1,21 @@
1
+ require 'tilt'
2
+
3
+ module Markaby
4
+ module Tilt
5
+ class Template < ::Tilt::Template
6
+ def evaluate(scope, locals, &block)
7
+ builder = Markaby::Builder.new({}, scope)
8
+ builder.locals = locals
9
+ builder.instance_eval(data, __FILE__, __LINE__)
10
+ builder.to_s
11
+ end
12
+
13
+ def compile!; end
14
+ end
15
+ end
16
+ end
17
+
18
+ module Tilt
19
+ MarkabyTemplate = Markaby::Tilt::Template
20
+ register "mab", MarkabyTemplate
21
+ end
data/lib/markaby.rb ADDED
@@ -0,0 +1,30 @@
1
+ # = About lib/markaby.rb
2
+ #
3
+ # By requiring <tt>lib/markaby</tt>, you can load Markaby's dependency (the Builder library,)
4
+ # as well as the full set of Markaby classes.
5
+ #
6
+ # For a full list of features and instructions, see the README.
7
+ $:.unshift File.expand_path(File.dirname(__FILE__))
8
+
9
+ # Markaby is a module containing all of the great Markaby classes that
10
+ # do such an excellent job.
11
+ #
12
+ # * Markaby::Builder: the class for actually calling the Ruby methods
13
+ # which write the HTML.
14
+ # * Markaby::CSSProxy: a class which adds element classes and IDs to
15
+ # elements when used within Markaby::Builder.
16
+ # * Markaby::MetAid: metaprogramming helper methods.
17
+ # * Markaby::Tags: lists the roles of various XHTML tags to help Builder
18
+ # use these tags as they are intended.
19
+ # * Markaby::Template: a class for hooking Markaby into Rails as a
20
+ # proper templating language.
21
+ module Markaby
22
+ version_file = File.expand_path(File.dirname(__FILE__) + "/../VERSION")
23
+ VERSION = File.read(version_file).strip
24
+
25
+ class InvalidXhtmlError < Exception; end
26
+ end
27
+
28
+ require 'builder' unless defined?(Builder)
29
+ require 'markaby/builder'
30
+ require 'markaby/cssproxy'
@@ -0,0 +1,40 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ class BuilderTest < Test::Unit::TestCase
4
+ def setup
5
+ Markaby::Builder.restore_defaults!
6
+ end
7
+
8
+ def teardown
9
+ Markaby::Builder.restore_defaults!
10
+ end
11
+
12
+ def test_method_missing_is_private
13
+ assert Markaby::Builder.private_instance_methods.include?("method_missing")
14
+ end
15
+
16
+ # setting options
17
+ def test_should_be_able_to_restore_defaults_after_setting
18
+ Markaby::Builder.set :indent, 2
19
+ Markaby::Builder.restore_defaults!
20
+
21
+ assert_equal 0, Markaby::Builder.get(:indent)
22
+ end
23
+
24
+ def test_should_be_able_set_global_options
25
+ Markaby::Builder.set :indent, 2
26
+ assert_equal 2, Markaby::Builder.get(:indent)
27
+ end
28
+
29
+ # internal clobbering by passed in assigns
30
+ def test_internal_helpers_ivar_should_not_be_overwritten_by_assigns
31
+ helper = Class.new do
32
+ def some_method
33
+ "a value"
34
+ end
35
+ end.new
36
+
37
+ builder = Markaby::Builder.new({:helpers => nil}, helper)
38
+ assert_equal "a value", builder.some_method
39
+ end
40
+ end
@@ -0,0 +1,44 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ class CssProxyTest < Test::Unit::TestCase
4
+ def test_method_missing_is_private
5
+ assert Markaby::CssProxy.private_instance_methods.include?("method_missing")
6
+ end
7
+
8
+ def mock_builder
9
+ mock_builder = Class.new do
10
+ def tag!(*args); end
11
+ end.new
12
+ end
13
+
14
+ def test_responds_to_everything
15
+ proxy = Markaby::CssProxy.new(mock_builder, 'stream', :sym)
16
+
17
+ assert proxy.respond_to?(:any_method)
18
+ assert proxy.respond_to?(:foobarbazasdfasdfadfs)
19
+ end
20
+
21
+ def test_does_not_respond_to_method_missing
22
+ proxy = Markaby::CssProxy.new(mock_builder, 'stream', :sym)
23
+
24
+ assert !proxy.respond_to?(:method_missing)
25
+ end
26
+
27
+ def test_does_respond_to_private_instance_methods_with_private_flag_set_to_true
28
+ proxy = Markaby::CssProxy.new(mock_builder, 'stream', :sym)
29
+
30
+ assert proxy.respond_to?(:method_missing, true)
31
+ end
32
+
33
+ def test_does_not_respond_to_private_instance_methods_with_private_flag_set_to_false
34
+ proxy = Markaby::CssProxy.new(mock_builder, 'stream', :sym)
35
+
36
+ assert !proxy.respond_to?(:method_missing, false)
37
+ end
38
+
39
+ def test_respond_to_should_always_return_boolean
40
+ proxy = Markaby::CssProxy.new(mock_builder, 'stream', :sym)
41
+
42
+ assert_equal proxy.respond_to?(:method_missing, :a_value), true
43
+ end
44
+ end
@@ -0,0 +1,7 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ class FragmentTest < Test::Unit::TestCase
4
+ def test_method_missing_is_private
5
+ assert Markaby::Fragment.private_instance_methods.include?("method_missing")
6
+ end
7
+ end
@@ -0,0 +1 @@
1
+ text "_why?"
@@ -0,0 +1,207 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ class MarkabyTest < Test::Unit::TestCase
4
+ def teardown
5
+ Markaby::Builder.restore_defaults!
6
+ end
7
+
8
+ def test_simple
9
+ assert_equal "<hr/>", mab { hr }
10
+ assert_equal "<hr/><br/>", mab { hr; br }
11
+ assert_equal "<p>foo</p>", mab { p 'foo' }
12
+ assert_equal "<p>foo</p>", mab { p { 'foo' } }
13
+ end
14
+
15
+ def test_classes_and_ids
16
+ assert_equal %{<div class="one"></div>}, mab { div.one '' }
17
+ assert_equal %{<div class="one two"></div>}, mab { div.one.two '' }
18
+ assert_equal %{<div id="three"></div>}, mab { div.three! '' }
19
+ assert_equal %{<hr class="hidden"/>}, mab { hr.hidden }
20
+ assert_equal %{<input class="foo" name="bar" id="bar"/>}, mab { input.foo :id => 'bar' }
21
+ end
22
+
23
+ def test_escaping
24
+ assert_equal "<h1>Apples &amp; Oranges</h1>", mab { h1 'Apples & Oranges' }
25
+ assert_equal "<h1>Apples & Oranges</h1>", mab { h1 { 'Apples & Oranges' } }
26
+ assert_equal "<h1 class=\"fruits&amp;floots\">Apples</h1>", mab { h1 'Apples', :class => 'fruits&floots' }
27
+ end
28
+
29
+ def test_capture
30
+ builder = Markaby::Builder.new
31
+ assert builder.to_s.empty?
32
+ assert_equal "<h1>TEST</h1>", builder.capture { h1 'TEST' }
33
+ assert builder.to_s.empty?
34
+ assert mab { capture { h1 'hello world' }; nil }.empty?
35
+ assert_equal mab { div { h1 'TEST' } }, mab { div { capture { h1 'TEST' } } }
36
+ end
37
+
38
+ def test_ivars
39
+ html = "<div><h1>Steve</h1><div><h2>Gerald</h2></div><h3>Gerald</h3></div>"
40
+ assert_equal html, mab { div { @name = 'Steve'; h1 @name; div { @name = 'Gerald'; h2 @name }; h3 @name } }
41
+ assert_equal html, mab { div { @name = 'Steve'; h1 @name; self << capture { div { @name = 'Gerald'; h2 @name } }; h3 @name } }
42
+ assert_equal html, mab(:name => 'Steve') { div { h1 @name; self << capture { div { @name = 'Gerald'; h2 @name } }; h3 @name } }
43
+ end
44
+
45
+ def test_ivars_without_at_symbol
46
+ assert_equal "<h1>Hello World</h1>", mab { @message = 'Hello World'; h1 message }
47
+ end
48
+
49
+ def spec_helpers
50
+ Markaby::Builder.ignored_helpers.clear
51
+ assert_equal %{squirrels}, mab({}, MarkabyTestHelpers) { pluralize('squirrel') }
52
+ assert_equal %{<a href="">edit</a>}, mab({}, MarkabyTestHelpers) { link_to('edit') }
53
+ assert mab({}, MarkabyTestHelpers) { @output_helpers = false; link_to('edit'); nil }.empty?
54
+ Markaby::Builder.ignore_helpers :pluralize
55
+ assert_exception(NoMethodError, "undefined method `pluralize'", {}, MarkabyTestHelpers) { pluralize('squirrel') }
56
+ end
57
+
58
+ def test_uses_helper_instance_variable
59
+ helper = Module.new do
60
+ @some_ivar = :ivar_value
61
+ end
62
+
63
+ builder = Markaby::Builder.new({}, helper)
64
+ assert_equal :ivar_value, builder.some_ivar
65
+ end
66
+
67
+ it "can assign helpers after instantiation" do
68
+ helper = mock 'helper', :foo => :bar
69
+
70
+ builder = Markaby::Builder.new
71
+ builder.helper = helper
72
+ assert_equal :bar, builder.foo
73
+ end
74
+
75
+ it "should be able to set a local" do
76
+ builder = Markaby::Builder.new
77
+ builder.locals = { :foo => "bar" }
78
+ builder.foo.should == "bar"
79
+ end
80
+
81
+ it "should be able to set a different local value" do
82
+ builder = Markaby::Builder.new
83
+ builder.locals = { :foo => "baz" }
84
+ builder.foo.should == "baz"
85
+ end
86
+
87
+ it "should assign the correct key" do
88
+ builder = Markaby::Builder.new
89
+ builder.locals = { :key => :value }
90
+ builder.key.should == :value
91
+ end
92
+
93
+ it "should be able to assign multiple locals" do
94
+ builder = Markaby::Builder.new
95
+
96
+ builder.locals = { :one => "two", :three => "four" }
97
+
98
+ builder.one.should == "two"
99
+ builder.three.should == "four"
100
+ end
101
+
102
+ def test_builder_bang_methods
103
+ assert_equal "<?xml version=\"1.0\" encoding=\"UTF-8\"?>", mab { instruct! }
104
+ end
105
+
106
+ def test_fragments
107
+ assert_equal %{<div><h1>Monkeys</h1><h2>Giraffes <small>Miniature</small> and <strong>Large</strong></h2><h3>Donkeys</h3><h4>Parakeet <b><i>Innocent IV</i></b> in Classic Chartreuse</h4></div>},
108
+ mab { div { h1 "Monkeys"; h2 { "Giraffes #{small 'Miniature' } and #{strong 'Large'}" }; h3 "Donkeys"; h4 { "Parakeet #{b { i 'Innocent IV' }} in Classic Chartreuse" } } }
109
+ assert_equal %{<div><h1>Monkeys</h1><h2>Giraffes <strong>Miniature</strong></h2><h3>Donkeys</h3></div>},
110
+ mab { div { h1 "Monkeys"; h2 { "Giraffes #{strong 'Miniature' }" }; h3 "Donkeys" } }
111
+ 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>},
112
+ mab { div { @a = small 'Miniature'; @b = strong 'Large'; h1 "Monkeys"; h2 { "Giraffes #{@a} and #{@b}" }; h3 "Donkeys"; h4 { "Parakeet #{@b} as well..." } } }
113
+ end
114
+
115
+ def test_invalid_xhtml
116
+ assert_exception(NoMethodError, "undefined method `dav'") { dav {} }
117
+ assert_exception(Markaby::InvalidXhtmlError, "no attribute `styl' on div elements") { div(:styl => 'ok') {} }
118
+ assert_exception(Markaby::InvalidXhtmlError, "no attribute `class' on tbody elements") { tbody.okay {} }
119
+ end
120
+
121
+ def test_full_doc_transitional
122
+ doc = mab { xhtml_transitional { head { title 'OKay' } } }
123
+ assert doc =~ /^<\?xml version="1.0" encoding="UTF-8"\?>/
124
+ assert doc.include?(%{"-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">})
125
+ assert doc.include?(%{<title>OKay</title>})
126
+ end
127
+
128
+ def test_full_doc_strict
129
+ doc = mab { xhtml_strict { head { title 'OKay' } } }
130
+ assert doc =~ /^<\?xml version="1.0" encoding="UTF-8"\?>/
131
+ assert doc.include?(%{"-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">})
132
+ assert doc.include?(%{<title>OKay</title>})
133
+ end
134
+
135
+ def test_full_doc_frameset
136
+ doc = mab { xhtml_frameset { head { title 'OKay' } } }
137
+ assert doc =~ /^<\?xml version="1.0" encoding="UTF-8"\?>/
138
+ assert doc.include?(%{"-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">})
139
+ assert doc.include?(%{<title>OKay</title>})
140
+ end
141
+
142
+ def test_root_attributes_can_be_changed
143
+ doc = mab { xhtml_strict(:lang => 'fr') { head { title { 'Salut!' } } } }
144
+ assert doc.include?(%{"-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">})
145
+ assert doc.include?(%{<title>Salut!</title>})
146
+ assert doc.include?(%{ lang="fr"})
147
+ end
148
+
149
+ def version_file
150
+ File.expand_path(File.dirname(__FILE__) + "/../../VERSION")
151
+ end
152
+
153
+ def test_markaby_should_have_correct_version
154
+ assert_equal Markaby::VERSION, File.read(version_file).strip
155
+ end
156
+
157
+ def test_duplicate_usage_of_same_id
158
+ assert_raises Markaby::InvalidXhtmlError do
159
+ mab do
160
+ p.one!
161
+ p.one!
162
+ end
163
+ end
164
+ end
165
+
166
+ # auto validation
167
+
168
+ def test_tagging_with_invalid_tag_should_raise_error
169
+ assert_raises Markaby::InvalidXhtmlError do
170
+ mab do
171
+ tag! :an_invalid_tag
172
+ end
173
+ end
174
+ end
175
+
176
+ def test_self_closing_html_tag_with_block_throws_errors
177
+ assert_raises Markaby::InvalidXhtmlError do
178
+ mab do
179
+ html_tag :img do
180
+ end
181
+ end
182
+ end
183
+ end
184
+
185
+ def test_local_assigning
186
+ builder = Markaby::Builder.new(:variable => :a_value)
187
+
188
+ assert_equal :a_value, builder.variable
189
+ end
190
+
191
+ def test_local_assignment_with_strings
192
+ builder = Markaby::Builder.new("variable" => :a_value)
193
+ assert_equal :a_value, builder.variable
194
+ end
195
+
196
+ def test_local_assignment_prefers_symbols_to_strings
197
+ builder = Markaby::Builder.new("variable" => "string_value", :variable => :symbol_value)
198
+ assert_equal :symbol_value, builder.variable
199
+ end
200
+
201
+ def test_method_missing_should_call_tag_if_no_tagset_present
202
+ Markaby::Builder.set(:tagset, nil)
203
+
204
+ builder = Markaby::Builder.new
205
+ assert_equal "<something/>", builder.something
206
+ end
207
+ end
@@ -0,0 +1,20 @@
1
+ require 'test/unit'
2
+
3
+ unless defined?(RUNNING_RAILS)
4
+ MARKABY_ROOT = File.join(File.dirname(__FILE__), "..", "..", "..")
5
+ rails_root = File.join(MARKABY_ROOT, "..", "..", "..")
6
+ RAILS_BOOT_FILE = File.join(rails_root, "config", "boot.rb")
7
+
8
+ RUNNING_RAILS = File.exists?(RAILS_BOOT_FILE) ? true : false
9
+ end
10
+
11
+ if RUNNING_RAILS
12
+ require RAILS_BOOT_FILE
13
+ Rails::Initializer.run
14
+ require 'action_controller/test_process'
15
+
16
+ $:.unshift MARKABY_ROOT
17
+ require 'init'
18
+ else
19
+ warn "Skipping rails specific tests"
20
+ end
@@ -0,0 +1,3 @@
1
+ ul do
2
+ li "smtlaissezfaire"
3
+ end
@@ -0,0 +1 @@
1
+ link_to "bar", "/foo"
@@ -0,0 +1,7 @@
1
+ div {
2
+ ul {
3
+ li 'one'
4
+ li 'two'
5
+ li supercalifragilisticexpialidocious
6
+ }
7
+ }
@@ -0,0 +1,5 @@
1
+ ul do
2
+ li "smt"
3
+ li "joho"
4
+ li "spox"
5
+ end
@@ -0,0 +1,3 @@
1
+ ul do
2
+ li "Scott"
3
+ end
@@ -0,0 +1 @@
1
+ render :partial => "a_partial"
@@ -0,0 +1,7 @@
1
+ ul do
2
+ authors = ["smtlaissezfaire"]
3
+
4
+ authors.each do |author|
5
+ render :partial => "partial_child_with_locals", :locals => {:author => author}
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ ul do
2
+ li "smtlaissezfaire"
3
+ end
@@ -0,0 +1,3 @@
1
+ ul do
2
+ li @user
3
+ end
@@ -0,0 +1 @@
1
+ Hello, from erb!