Markaby 0.6.3

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