actionpack 1.11.2 → 1.12.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (149) hide show
  1. data/CHANGELOG +392 -5
  2. data/lib/action_controller.rb +8 -4
  3. data/lib/action_controller/assertions.rb +9 -10
  4. data/lib/action_controller/base.rb +177 -88
  5. data/lib/action_controller/benchmarking.rb +5 -5
  6. data/lib/action_controller/caching.rb +44 -36
  7. data/lib/action_controller/cgi_ext/cgi_methods.rb +71 -6
  8. data/lib/action_controller/cgi_ext/cookie_performance_fix.rb +1 -1
  9. data/lib/action_controller/cgi_process.rb +36 -24
  10. data/lib/action_controller/components.rb +152 -52
  11. data/lib/action_controller/dependencies.rb +1 -1
  12. data/lib/action_controller/deprecated_redirects.rb +2 -2
  13. data/lib/action_controller/deprecated_request_methods.rb +34 -0
  14. data/lib/action_controller/filters.rb +59 -19
  15. data/lib/action_controller/flash.rb +53 -47
  16. data/lib/action_controller/helpers.rb +2 -2
  17. data/lib/action_controller/integration.rb +524 -0
  18. data/lib/action_controller/layout.rb +58 -23
  19. data/lib/action_controller/mime_responds.rb +163 -0
  20. data/lib/action_controller/mime_type.rb +142 -0
  21. data/lib/action_controller/pagination.rb +13 -7
  22. data/lib/action_controller/request.rb +59 -56
  23. data/lib/action_controller/rescue.rb +1 -1
  24. data/lib/action_controller/routing.rb +29 -10
  25. data/lib/action_controller/scaffolding.rb +8 -0
  26. data/lib/action_controller/session/active_record_store.rb +21 -10
  27. data/lib/action_controller/session/mem_cache_store.rb +18 -12
  28. data/lib/action_controller/session_management.rb +30 -11
  29. data/lib/action_controller/templates/rescues/_trace.rhtml +1 -1
  30. data/lib/action_controller/templates/scaffolds/layout.rhtml +4 -4
  31. data/lib/action_controller/templates/scaffolds/list.rhtml +1 -1
  32. data/lib/action_controller/test_process.rb +189 -118
  33. data/lib/action_controller/vendor/html-scanner/html/node.rb +20 -1
  34. data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +3 -0
  35. data/lib/action_controller/vendor/html-scanner/html/version.rb +1 -1
  36. data/lib/action_controller/vendor/xml_node.rb +97 -0
  37. data/lib/action_controller/verification.rb +2 -0
  38. data/lib/action_pack/version.rb +3 -3
  39. data/lib/action_view.rb +0 -2
  40. data/lib/action_view/base.rb +109 -36
  41. data/lib/action_view/compiled_templates.rb +1 -1
  42. data/lib/action_view/helpers/active_record_helper.rb +4 -2
  43. data/lib/action_view/helpers/asset_tag_helper.rb +6 -7
  44. data/lib/action_view/helpers/capture_helper.rb +49 -12
  45. data/lib/action_view/helpers/date_helper.rb +14 -4
  46. data/lib/action_view/helpers/form_helper.rb +136 -20
  47. data/lib/action_view/helpers/form_options_helper.rb +29 -7
  48. data/lib/action_view/helpers/form_tag_helper.rb +22 -20
  49. data/lib/action_view/helpers/java_script_macros_helper.rb +29 -9
  50. data/lib/action_view/helpers/javascript_helper.rb +50 -446
  51. data/lib/action_view/helpers/javascripts/controls.js +95 -30
  52. data/lib/action_view/helpers/javascripts/dragdrop.js +161 -21
  53. data/lib/action_view/helpers/javascripts/effects.js +310 -211
  54. data/lib/action_view/helpers/javascripts/prototype.js +228 -28
  55. data/lib/action_view/helpers/number_helper.rb +9 -9
  56. data/lib/action_view/helpers/pagination_helper.rb +1 -1
  57. data/lib/action_view/helpers/prototype_helper.rb +900 -0
  58. data/lib/action_view/helpers/scriptaculous_helper.rb +135 -0
  59. data/lib/action_view/helpers/text_helper.rb +7 -6
  60. data/lib/action_view/helpers/url_helper.rb +23 -14
  61. data/lib/action_view/partials.rb +12 -4
  62. data/rakefile +13 -5
  63. data/test/abstract_unit.rb +4 -3
  64. data/test/active_record_unit.rb +88 -0
  65. data/test/{controller → activerecord}/active_record_assertions_test.rb +7 -50
  66. data/test/{controller → activerecord}/active_record_store_test.rb +27 -4
  67. data/test/activerecord/pagination_test.rb +161 -0
  68. data/test/controller/action_pack_assertions_test.rb +18 -15
  69. data/test/controller/base_test.rb +31 -42
  70. data/test/controller/benchmark_test.rb +8 -11
  71. data/test/controller/capture_test.rb +33 -1
  72. data/test/controller/cgi_test.rb +33 -0
  73. data/test/controller/custom_handler_test.rb +8 -0
  74. data/test/controller/fake_controllers.rb +9 -17
  75. data/test/controller/filters_test.rb +32 -3
  76. data/test/controller/flash_test.rb +26 -41
  77. data/test/controller/fragment_store_setting_test.rb +1 -1
  78. data/test/controller/layout_test.rb +73 -0
  79. data/test/controller/mime_responds_test.rb +257 -0
  80. data/test/controller/mime_type_test.rb +24 -0
  81. data/test/controller/new_render_test.rb +157 -1
  82. data/test/controller/redirect_test.rb +23 -0
  83. data/test/controller/render_test.rb +54 -56
  84. data/test/controller/request_test.rb +25 -0
  85. data/test/controller/routing_test.rb +74 -66
  86. data/test/controller/test_test.rb +66 -1
  87. data/test/controller/verification_test.rb +3 -1
  88. data/test/controller/webservice_test.rb +255 -0
  89. data/test/fixtures/companies.yml +24 -0
  90. data/test/fixtures/company.rb +9 -0
  91. data/test/fixtures/db_definitions/sqlite.sql +42 -0
  92. data/test/fixtures/developer.rb +7 -0
  93. data/test/fixtures/developers.yml +21 -0
  94. data/test/fixtures/developers_projects.yml +13 -0
  95. data/test/fixtures/layout_tests/layouts/controller_name_space/nested.rhtml +1 -0
  96. data/test/fixtures/layout_tests/layouts/item.rhtml +1 -0
  97. data/test/fixtures/layout_tests/layouts/layout_test.rhtml +1 -0
  98. data/test/fixtures/layout_tests/layouts/third_party_template_library.mab +1 -0
  99. data/test/fixtures/layout_tests/views/hello.rhtml +1 -0
  100. data/test/fixtures/multipart/mona_lisa.jpg +0 -0
  101. data/test/fixtures/project.rb +3 -0
  102. data/test/fixtures/projects.yml +7 -0
  103. data/test/fixtures/replies.yml +13 -0
  104. data/test/fixtures/reply.rb +5 -0
  105. data/test/fixtures/respond_to/all_types_with_layout.rhtml +1 -0
  106. data/test/fixtures/respond_to/all_types_with_layout.rjs +1 -0
  107. data/test/fixtures/respond_to/layouts/standard.rhtml +1 -0
  108. data/test/fixtures/respond_to/using_defaults.rhtml +1 -0
  109. data/test/fixtures/respond_to/using_defaults.rjs +1 -0
  110. data/test/fixtures/respond_to/using_defaults.rxml +1 -0
  111. data/test/fixtures/respond_to/using_defaults_with_type_list.rhtml +1 -0
  112. data/test/fixtures/respond_to/using_defaults_with_type_list.rjs +1 -0
  113. data/test/fixtures/respond_to/using_defaults_with_type_list.rxml +1 -0
  114. data/test/fixtures/test/block_content_for.rhtml +2 -0
  115. data/test/fixtures/test/delete_with_js.rjs +2 -0
  116. data/test/fixtures/test/dot.directory/render_file_with_ivar.rhtml +1 -0
  117. data/test/fixtures/test/enum_rjs_test.rjs +6 -0
  118. data/test/fixtures/test/erb_content_for.rhtml +2 -0
  119. data/test/fixtures/test/hello_world.rxml +3 -0
  120. data/test/fixtures/test/hello_world_with_layout_false.rhtml +1 -0
  121. data/test/fixtures/test/non_erb_block_content_for.rxml +4 -0
  122. data/test/fixtures/topic.rb +3 -0
  123. data/test/fixtures/topics.yml +22 -0
  124. data/test/template/active_record_helper_test.rb +4 -0
  125. data/test/template/asset_tag_helper_test.rb +7 -2
  126. data/test/template/date_helper_test.rb +39 -2
  127. data/test/template/form_helper_test.rb +238 -5
  128. data/test/template/form_options_helper_test.rb +78 -0
  129. data/test/template/form_tag_helper_test.rb +11 -0
  130. data/test/template/java_script_macros_helper_test.rb +51 -6
  131. data/test/template/javascript_helper_test.rb +7 -153
  132. data/test/template/number_helper_test.rb +14 -13
  133. data/test/template/prototype_helper_test.rb +423 -0
  134. data/test/template/scriptaculous_helper_test.rb +90 -0
  135. data/test/template/text_helper_test.rb +12 -9
  136. data/test/template/url_helper_test.rb +31 -15
  137. metadata +291 -246
  138. data/lib/action_controller/cgi_ext/multipart_progress.rb +0 -169
  139. data/lib/action_controller/upload_progress.rb +0 -473
  140. data/lib/action_controller/vendor/html-scanner/html/node.rb.rej +0 -17
  141. data/lib/action_view/helpers/upload_progress_helper.rb +0 -433
  142. data/lib/action_view/vendor/builder.rb +0 -13
  143. data/lib/action_view/vendor/builder/blankslate.rb +0 -53
  144. data/lib/action_view/vendor/builder/xmlbase.rb +0 -143
  145. data/lib/action_view/vendor/builder/xmlevents.rb +0 -63
  146. data/lib/action_view/vendor/builder/xmlmarkup.rb +0 -308
  147. data/test/controller/multipart_progress_testx.rb +0 -365
  148. data/test/controller/upload_progress_testx.rb +0 -89
  149. data/test/template/upload_progress_helper_testx.rb +0 -136
@@ -1,53 +0,0 @@
1
- #!/usr/bin/env ruby
2
- #--
3
- # Copyright 2004 by Jim Weirich (jim@weirichhouse.org).
4
- # All rights reserved.
5
-
6
- # Permission is granted for use, copying, modification, distribution,
7
- # and distribution of modified versions of this work as long as the
8
- # above copyright notice is included.
9
- #++
10
-
11
- module Builder #:nodoc:
12
-
13
- # BlankSlate provides an abstract base class with no predefined
14
- # methods (except for <tt>\_\_send__</tt> and <tt>\_\_id__</tt>).
15
- # BlankSlate is useful as a base class when writing classes that
16
- # depend upon <tt>method_missing</tt> (e.g. dynamic proxies).
17
- class BlankSlate #:nodoc:
18
- class << self
19
- def hide(name)
20
- undef_method name if
21
- instance_methods.include?(name.to_s) and
22
- name !~ /^(__|instance_eval)/
23
- end
24
- end
25
-
26
- instance_methods.each { |m| hide(m) }
27
- end
28
- end
29
-
30
- # Since Ruby is very dynamic, methods added to the ancestors of
31
- # BlankSlate <em>after BlankSlate is defined</em> will show up in the
32
- # list of available BlankSlate methods. We handle this by defining a hook in the Object and Kernel classes that will hide any defined
33
- module Kernel #:nodoc:
34
- class << self
35
- alias_method :blank_slate_method_added, :method_added
36
- def method_added(name)
37
- blank_slate_method_added(name)
38
- return if self != Kernel
39
- Builder::BlankSlate.hide(name)
40
- end
41
- end
42
- end
43
-
44
- class Object #:nodoc:
45
- class << self
46
- alias_method :blank_slate_method_added, :method_added
47
- def method_added(name)
48
- blank_slate_method_added(name)
49
- return if self != Object
50
- Builder::BlankSlate.hide(name)
51
- end
52
- end
53
- end
@@ -1,143 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'builder/blankslate'
4
-
5
- module Builder #:nodoc:
6
-
7
- # Generic error for builder
8
- class IllegalBlockError < RuntimeError #:nodoc:
9
- end
10
-
11
- # XmlBase is a base class for building XML builders. See
12
- # Builder::XmlMarkup and Builder::XmlEvents for examples.
13
- class XmlBase < BlankSlate #:nodoc:
14
-
15
- # Create an XML markup builder.
16
- #
17
- # out:: Object receiving the markup.1 +out+ must respond to
18
- # <tt><<</tt>.
19
- # indent:: Number of spaces used for indentation (0 implies no
20
- # indentation and no line breaks).
21
- # initial:: Level of initial indentation.
22
- #
23
- def initialize(indent=0, initial=0)
24
- @indent = indent
25
- @level = initial
26
- end
27
-
28
- # Create a tag named +sym+. Other than the first argument which
29
- # is the tag name, the arguements are the same as the tags
30
- # implemented via <tt>method_missing</tt>.
31
- def tag!(sym, *args, &block)
32
- self.__send__(sym, *args, &block)
33
- end
34
-
35
- # Create XML markup based on the name of the method. This method
36
- # is never invoked directly, but is called for each markup method
37
- # in the markup block.
38
- def method_missing(sym, *args, &block)
39
- text = nil
40
- attrs = nil
41
- sym = "#{sym}:#{args.shift}" if args.first.kind_of?(Symbol)
42
- args.each do |arg|
43
- case arg
44
- when Hash
45
- attrs ||= {}
46
- attrs.merge!(arg)
47
- else
48
- text ||= ''
49
- text << arg.to_s
50
- end
51
- end
52
- if block
53
- unless text.nil?
54
- raise ArgumentError, "XmlMarkup cannot mix a text argument with a block"
55
- end
56
- _capture_outer_self(block) if @self.nil?
57
- _indent
58
- _start_tag(sym, attrs)
59
- _newline
60
- _nested_structures(block)
61
- _indent
62
- _end_tag(sym)
63
- _newline
64
- elsif text.nil?
65
- _indent
66
- _start_tag(sym, attrs, true)
67
- _newline
68
- else
69
- _indent
70
- _start_tag(sym, attrs)
71
- text! text
72
- _end_tag(sym)
73
- _newline
74
- end
75
- @target
76
- end
77
-
78
- # Append text to the output target. Escape any markup. May be
79
- # used within the markup brackets as:
80
- #
81
- # builder.p { br; text! "HI" } #=> <p><br/>HI</p>
82
- def text!(text)
83
- _text(_escape(text))
84
- end
85
-
86
- # Append text to the output target without escaping any markup.
87
- # May be used within the markup brackets as:
88
- #
89
- # builder.p { |x| x << "<br/>HI" } #=> <p><br/>HI</p>
90
- #
91
- # This is useful when using non-builder enabled software that
92
- # generates strings. Just insert the string directly into the
93
- # builder without changing the inserted markup.
94
- #
95
- # It is also useful for stacking builder objects. Builders only
96
- # use <tt><<</tt> to append to the target, so by supporting this
97
- # method/operation builders can use other builders as their
98
- # targets.
99
- def <<(text)
100
- _text(text)
101
- end
102
-
103
- # For some reason, nil? is sent to the XmlMarkup object. If nil?
104
- # is not defined and method_missing is invoked, some strange kind
105
- # of recursion happens. Since nil? won't ever be an XML tag, it
106
- # is pretty safe to define it here. (Note: this is an example of
107
- # cargo cult programming,
108
- # cf. http://fishbowl.pastiche.org/2004/10/13/cargo_cult_programming).
109
- def nil?
110
- false
111
- end
112
-
113
- private
114
-
115
- def _escape(text)
116
- text.
117
- gsub(%r{&}, '&amp;').
118
- gsub(%r{<}, '&lt;').
119
- gsub(%r{>}, '&gt;')
120
- end
121
-
122
- def _capture_outer_self(block)
123
- @self = eval("self", block)
124
- end
125
-
126
- def _newline
127
- return if @indent == 0
128
- text! "\n"
129
- end
130
-
131
- def _indent
132
- return if @indent == 0 || @level == 0
133
- text!(" " * (@level * @indent))
134
- end
135
-
136
- def _nested_structures(block)
137
- @level += 1
138
- block.call(self)
139
- ensure
140
- @level -= 1
141
- end
142
- end
143
- end
@@ -1,63 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- #--
4
- # Copyright 2004 by Jim Weirich (jim@weirichhouse.org).
5
- # All rights reserved.
6
-
7
- # Permission is granted for use, copying, modification, distribution,
8
- # and distribution of modified versions of this work as long as the
9
- # above copyright notice is included.
10
- #++
11
-
12
- require 'builder/xmlmarkup'
13
-
14
- module Builder
15
-
16
- # Create a series of SAX-like XML events (e.g. start_tag, end_tag)
17
- # from the markup code. XmlEvent objects are used in a way similar
18
- # to XmlMarkup objects, except that a series of events are generated
19
- # and passed to a handler rather than generating character-based
20
- # markup.
21
- #
22
- # Usage:
23
- # xe = Builder::XmlEvents.new(hander)
24
- # xe.title("HI") # Sends start_tag/end_tag/text messages to the handler.
25
- #
26
- # Indentation may also be selected by providing value for the
27
- # indentation size and initial indentation level.
28
- #
29
- # xe = Builder::XmlEvents.new(handler, indent_size, initial_indent_level)
30
- #
31
- # == XML Event Handler
32
- #
33
- # The handler object must expect the following events.
34
- #
35
- # [<tt>start_tag(tag, attrs)</tt>]
36
- # Announces that a new tag has been found. +tag+ is the name of
37
- # the tag and +attrs+ is a hash of attributes for the tag.
38
- #
39
- # [<tt>end_tag(tag)</tt>]
40
- # Announces that an end tag for +tag+ has been found.
41
- #
42
- # [<tt>text(text)</tt>]
43
- # Announces that a string of characters (+text+) has been found.
44
- # A series of characters may be broken up into more than one
45
- # +text+ call, so the client cannot assume that a single
46
- # callback contains all the text data.
47
- #
48
- class XmlEvents < XmlMarkup #:nodoc:
49
- def text!(text)
50
- @target.text(text)
51
- end
52
-
53
- def _start_tag(sym, attrs, end_too=false)
54
- @target.start_tag(sym, attrs)
55
- _end_tag(sym) if end_too
56
- end
57
-
58
- def _end_tag(sym)
59
- @target.end_tag(sym)
60
- end
61
- end
62
-
63
- end
@@ -1,308 +0,0 @@
1
- #!/usr/bin/env ruby
2
- #--
3
- # Copyright 2004 by Jim Weirich (jim@weirichhouse.org).
4
- # All rights reserved.
5
-
6
- # Permission is granted for use, copying, modification, distribution,
7
- # and distribution of modified versions of this work as long as the
8
- # above copyright notice is included.
9
- #++
10
-
11
- # Provide a flexible and easy to use Builder for creating XML markup.
12
- # See XmlBuilder for usage details.
13
-
14
- require 'builder/xmlbase'
15
-
16
- module Builder
17
-
18
- # Create XML markup easily. All (well, almost all) methods sent to
19
- # an XmlMarkup object will be translated to the equivalent XML
20
- # markup. Any method with a block will be treated as an XML markup
21
- # tag with nested markup in the block.
22
- #
23
- # Examples will demonstrate this easier than words. In the
24
- # following, +xm+ is an +XmlMarkup+ object.
25
- #
26
- # xm.em("emphasized") # => <em>emphasized</em>
27
- # xm.em { xmm.b("emp & bold") } # => <em><b>emph &amp; bold</b></em>
28
- # xm.a("A Link", "href"=>"http://onestepback.org")
29
- # # => <a href="http://onestepback.org">A Link</a>
30
- # xm.div { br } # => <div><br/></div>
31
- # xm.target("name"=>"compile", "option"=>"fast")
32
- # # => <target option="fast" name="compile"\>
33
- # # NOTE: order of attributes is not specified.
34
- #
35
- # xm.instruct! # <?xml version="1.0" encoding="UTF-8"?>
36
- # xm.html { # <html>
37
- # xm.head { # <head>
38
- # xm.title("History") # <title>History</title>
39
- # } # </head>
40
- # xm.body { # <body>
41
- # xm.comment! "HI" # <!-- HI -->
42
- # xm.h1("Header") # <h1>Header</h1>
43
- # xm.p("paragraph") # <p>paragraph</p>
44
- # } # </body>
45
- # } # </html>
46
- #
47
- # == Notes:
48
- #
49
- # * The order that attributes are inserted in markup tags is
50
- # undefined.
51
- #
52
- # * Sometimes you wish to insert text without enclosing tags. Use
53
- # the <tt>text!</tt> method to accomplish this.
54
- #
55
- # Example:
56
- #
57
- # xm.div { # <div>
58
- # xm.text! "line"; xm.br # line<br/>
59
- # xm.text! "another line"; xmbr # another line<br/>
60
- # } # </div>
61
- #
62
- # * The special XML characters <, >, and & are converted to &lt;,
63
- # &gt; and &amp; automatically. Use the <tt><<</tt> operation to
64
- # insert text without modification.
65
- #
66
- # * Sometimes tags use special characters not allowed in ruby
67
- # identifiers. Use the <tt>tag!</tt> method to handle these
68
- # cases.
69
- #
70
- # Example:
71
- #
72
- # xml.tag!("SOAP:Envelope") { ... }
73
- #
74
- # will produce ...
75
- #
76
- # <SOAP:Envelope> ... </SOAP:Envelope>"
77
- #
78
- # <tt>tag!</tt> will also take text and attribute arguments (after
79
- # the tag name) like normal markup methods. (But see the next
80
- # bullet item for a better way to handle XML namespaces).
81
- #
82
- # * Direct support for XML namespaces is now available. If the
83
- # first argument to a tag call is a symbol, it will be joined to
84
- # the tag to produce a namespace:tag combination. It is easier to
85
- # show this than describe it.
86
- #
87
- # xml.SOAP :Envelope do ... end
88
- #
89
- # Just put a space before the colon in a namespace to produce the
90
- # right form for builder (e.g. "<tt>SOAP:Envelope</tt>" =>
91
- # "<tt>xml.SOAP :Envelope</tt>")
92
- #
93
- # * XmlMarkup builds the markup in any object (called a _target_)
94
- # that accepts the <tt><<</tt> method. If no target is given,
95
- # then XmlMarkup defaults to a string target.
96
- #
97
- # Examples:
98
- #
99
- # xm = Builder::XmlMarkup.new
100
- # result = xm.title("yada")
101
- # # result is a string containing the markup.
102
- #
103
- # buffer = ""
104
- # xm = Builder::XmlMarkup.new(buffer)
105
- # # The markup is appended to buffer (using <<)
106
- #
107
- # xm = Builder::XmlMarkup.new(STDOUT)
108
- # # The markup is written to STDOUT (using <<)
109
- #
110
- # xm = Builder::XmlMarkup.new
111
- # x2 = Builder::XmlMarkup.new(:target=>xm)
112
- # # Markup written to +x2+ will be send to +xm+.
113
- #
114
- # * Indentation is enabled by providing the number of spaces to
115
- # indent for each level as a second argument to XmlBuilder.new.
116
- # Initial indentation may be specified using a third parameter.
117
- #
118
- # Example:
119
- #
120
- # xm = Builder.new(:ident=>2)
121
- # # xm will produce nicely formatted and indented XML.
122
- #
123
- # xm = Builder.new(:indent=>2, :margin=>4)
124
- # # xm will produce nicely formatted and indented XML with 2
125
- # # spaces per indent and an over all indentation level of 4.
126
- #
127
- # builder = Builder::XmlMarkup.new(:target=>$stdout, :indent=>2)
128
- # builder.name { |b| b.first("Jim"); b.last("Weirich) }
129
- # # prints:
130
- # # <name>
131
- # # <first>Jim</first>
132
- # # <last>Weirich</last>
133
- # # </name>
134
- #
135
- # * The instance_eval implementation which forces self to refer to
136
- # the message receiver as self is now obsolete. We now use normal
137
- # block calls to execute the markup block. This means that all
138
- # markup methods must now be explicitly send to the xml builder.
139
- # For instance, instead of
140
- #
141
- # xml.div { strong("text") }
142
- #
143
- # you need to write:
144
- #
145
- # xml.div { xml.strong("text") }
146
- #
147
- # Although more verbose, the subtle change in semantics within the
148
- # block was found to be prone to error. To make this change a
149
- # little less cumbersome, the markup block now gets the markup
150
- # object sent as an argument, allowing you to use a shorter alias
151
- # within the block.
152
- #
153
- # For example:
154
- #
155
- # xml_builder = Builder::XmlMarkup.new
156
- # xml_builder.div { |xml|
157
- # xml.stong("text")
158
- # }
159
- #
160
- class XmlMarkup < XmlBase
161
-
162
- # Create an XML markup builder. Parameters are specified by an
163
- # option hash.
164
- #
165
- # :target=><em>target_object</em>::
166
- # Object receiving the markup. +out+ must respond to the
167
- # <tt><<</tt> operator. The default is a plain string target.
168
- # :indent=><em>indentation</em>::
169
- # Number of spaces used for indentation. The default is no
170
- # indentation and no line breaks.
171
- # :margin=><em>initial_indentation_level</em>::
172
- # Amount of initial indentation (specified in levels, not
173
- # spaces).
174
- #
175
- def initialize(options={})
176
- indent = options[:indent] || 0
177
- margin = options[:margin] || 0
178
- super(indent, margin)
179
- @target = options[:target] || ""
180
- end
181
-
182
- # Return the target of the builder.
183
- def target!
184
- @target
185
- end
186
-
187
- def comment!(comment_text)
188
- _ensure_no_block block_given?
189
- _special("<!-- ", " -->", comment_text, nil)
190
- end
191
-
192
- # Insert an XML declaration into the XML markup.
193
- #
194
- # For example:
195
- #
196
- # xml.declare! :ELEMENT, :blah, "yada"
197
- # # => <!ELEMENT blah "yada">
198
- def declare!(inst, *args, &block)
199
- _indent
200
- @target << "<!#{inst}"
201
- args.each do |arg|
202
- case arg
203
- when String
204
- @target << %{ "#{arg}"}
205
- when Symbol
206
- @target << " #{arg}"
207
- end
208
- end
209
- if block_given?
210
- @target << " ["
211
- _newline
212
- _nested_structures(block)
213
- @target << "]"
214
- end
215
- @target << ">"
216
- _newline
217
- end
218
-
219
- # Insert a processing instruction into the XML markup. E.g.
220
- #
221
- # For example:
222
- #
223
- # xml.instruct!
224
- # #=> <?xml version="1.0" encoding="UTF-8"?>
225
- # xml.instruct! :aaa, :bbb=>"ccc"
226
- # #=> <?aaa bbb="ccc"?>
227
- #
228
- def instruct!(directive_tag=:xml, attrs={})
229
- _ensure_no_block block_given?
230
- if directive_tag == :xml
231
- a = { :version=>"1.0", :encoding=>"UTF-8" }
232
- attrs = a.merge attrs
233
- end
234
- _special(
235
- "<?#{directive_tag}",
236
- "?>",
237
- nil,
238
- attrs,
239
- [:version, :encoding, :standalone])
240
- end
241
-
242
- # Surrounds the given text with a CDATA tag
243
- #
244
- # For example:
245
- #
246
- # xml.cdata! "blah blah blah"
247
- # # => <![CDATA[blah blah blah]]>
248
- def cdata!(text)
249
- _ensure_no_block block_given?
250
- _special("<![CDATA[", "]]>", text, nil)
251
- end
252
-
253
- private
254
-
255
- # NOTE: All private methods of a builder object are prefixed when
256
- # a "_" character to avoid possible conflict with XML tag names.
257
-
258
- # Insert text directly in to the builder's target.
259
- def _text(text)
260
- @target << text
261
- end
262
-
263
- # Insert special instruction.
264
- def _special(open, close, data=nil, attrs=nil, order=[])
265
- _indent
266
- @target << open
267
- @target << data if data
268
- _insert_attributes(attrs, order) if attrs
269
- @target << close
270
- _newline
271
- end
272
-
273
- # Start an XML tag. If <tt>end_too</tt> is true, then the start
274
- # tag is also the end tag (e.g. <br/>
275
- def _start_tag(sym, attrs, end_too=false)
276
- @target << "<#{sym}"
277
- _insert_attributes(attrs)
278
- @target << "/" if end_too
279
- @target << ">"
280
- end
281
-
282
- # Insert an ending tag.
283
- def _end_tag(sym)
284
- @target << "</#{sym}>"
285
- end
286
-
287
- # Insert the attributes (given in the hash).
288
- def _insert_attributes(attrs, order=[])
289
- return if attrs.nil?
290
- order.each do |k|
291
- v = attrs[k]
292
- @target << %{ #{k}="#{v}"} if v
293
- end
294
- attrs.each do |k, v|
295
- @target << %{ #{k}="#{v}"} unless order.member?(k)
296
- end
297
- end
298
-
299
- def _ensure_no_block(got_block)
300
- if got_block
301
- fail IllegalBlockError,
302
- "Blocks are not allowed on XML instructions"
303
- end
304
- end
305
-
306
- end
307
-
308
- end