~michaelforrest/use-case-mapper/trunk

« back to all changes in this revision

Viewing changes to vendor/rails/activesupport/lib/active_support/vendor/builder-2.1.2/builder/xmlbase.rb

  • Committer: Richard Lee (Canonical)
  • Date: 2010-10-15 15:17:58 UTC
  • mfrom: (190.1.3 use-case-mapper)
  • Revision ID: richard.lee@canonical.com-20101015151758-wcvmfxrexsongf9d
Merge

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/env ruby
2
 
 
3
 
require 'builder/blankslate'
4
 
 
5
 
module Builder
6
 
 
7
 
  # Generic error for builder
8
 
  class IllegalBlockError < RuntimeError; end
9
 
 
10
 
  # XmlBase is a base class for building XML builders.  See
11
 
  # Builder::XmlMarkup and Builder::XmlEvents for examples.
12
 
  class XmlBase < BlankSlate
13
 
 
14
 
    # Create an XML markup builder.
15
 
    #
16
 
    # out::     Object receiving the markup.  +out+ must respond to
17
 
    #           <tt><<</tt>.
18
 
    # indent::  Number of spaces used for indentation (0 implies no
19
 
    #           indentation and no line breaks).
20
 
    # initial:: Level of initial indentation.
21
 
    #
22
 
    def initialize(indent=0, initial=0)
23
 
      @indent = indent
24
 
      @level  = initial
25
 
    end
26
 
 
27
 
    # Create a tag named +sym+.  Other than the first argument which
28
 
    # is the tag name, the arguments are the same as the tags
29
 
    # implemented via <tt>method_missing</tt>.
30
 
    def tag!(sym, *args, &block)
31
 
      method_missing(sym.to_sym, *args, &block)
32
 
    end
33
 
 
34
 
    # Create XML markup based on the name of the method.  This method
35
 
    # is never invoked directly, but is called for each markup method
36
 
    # in the markup block.
37
 
    def method_missing(sym, *args, &block)
38
 
      text = nil
39
 
      attrs = nil
40
 
      sym = "#{sym}:#{args.shift}" if args.first.kind_of?(Symbol)
41
 
      args.each do |arg|
42
 
        case arg
43
 
        when Hash
44
 
          attrs ||= {}
45
 
          attrs.merge!(arg)
46
 
        else
47
 
          text ||= ''
48
 
          text << arg.to_s
49
 
        end
50
 
      end
51
 
      if block
52
 
        unless text.nil?
53
 
          raise ArgumentError, "XmlMarkup cannot mix a text argument with a block"
54
 
        end
55
 
        _indent
56
 
        _start_tag(sym, attrs)
57
 
        _newline
58
 
        _nested_structures(block)
59
 
        _indent
60
 
        _end_tag(sym)
61
 
        _newline
62
 
      elsif text.nil?
63
 
        _indent
64
 
        _start_tag(sym, attrs, true)
65
 
        _newline
66
 
      else
67
 
        _indent
68
 
        _start_tag(sym, attrs)
69
 
        text! text
70
 
        _end_tag(sym)
71
 
        _newline
72
 
      end
73
 
      @target
74
 
    end
75
 
 
76
 
    # Append text to the output target.  Escape any markup.  May be
77
 
    # used within the markup brackets as:
78
 
    #
79
 
    #   builder.p { |b| b.br; b.text! "HI" }   #=>  <p><br/>HI</p>
80
 
    def text!(text)
81
 
      _text(_escape(text))
82
 
    end
83
 
 
84
 
    # Append text to the output target without escaping any markup.
85
 
    # May be used within the markup brackets as:
86
 
    #
87
 
    #   builder.p { |x| x << "<br/>HI" }   #=>  <p><br/>HI</p>
88
 
    #
89
 
    # This is useful when using non-builder enabled software that
90
 
    # generates strings.  Just insert the string directly into the
91
 
    # builder without changing the inserted markup.
92
 
    #
93
 
    # It is also useful for stacking builder objects.  Builders only
94
 
    # use <tt><<</tt> to append to the target, so by supporting this
95
 
    # method/operation builders can use other builders as their
96
 
    # targets.
97
 
    def <<(text)
98
 
      _text(text)
99
 
    end
100
 
 
101
 
    # For some reason, nil? is sent to the XmlMarkup object.  If nil?
102
 
    # is not defined and method_missing is invoked, some strange kind
103
 
    # of recursion happens.  Since nil? won't ever be an XML tag, it
104
 
    # is pretty safe to define it here. (Note: this is an example of
105
 
    # cargo cult programming,
106
 
    # cf. http://fishbowl.pastiche.org/2004/10/13/cargo_cult_programming).
107
 
    def nil?
108
 
      false
109
 
    end
110
 
 
111
 
    private
112
 
 
113
 
    require 'builder/xchar'
114
 
    def _escape(text)
115
 
      text.to_xs
116
 
    end
117
 
 
118
 
    def _escape_quote(text)
119
 
      _escape(text).gsub(%r{"}, '&quot;')  # " WART
120
 
    end
121
 
 
122
 
    def _newline
123
 
      return if @indent == 0
124
 
      text! "\n"
125
 
    end
126
 
 
127
 
    def _indent
128
 
      return if @indent == 0 || @level == 0
129
 
      text!(" " * (@level * @indent))
130
 
    end
131
 
 
132
 
    def _nested_structures(block)
133
 
      @level += 1
134
 
      block.call(self)
135
 
    ensure
136
 
      @level -= 1
137
 
    end
138
 
  end
139
 
end