Tangerine (Class)

In: tangerine.rb
Parent: String

Tangerine — A general-purpose templating system Copyright (C) 2004 Christian Neukirchen <purl.org/net/chneukirchen>

Licensed under the same terms as Ruby itself.

Methods

Constants

VERSION = "0.3.1"
  Version information

Attributes

code  [R]  The generated code.
taglib  [RW]  The tag library being used.

Classes and Modules

Class Tangerine::FileLib
Class Tangerine::RFC822
Class Tangerine::XML

Public Class methods

Indent the string to depth, only subsequent lines.

[Source]

    # File tangerine.rb, line 19
19:   def self.indent(depth, string)
20:     string.gsub(/\n^/, "\n" + ' '*depth)
21:   end

Create, parse and compile a new Tangerine template given in template.

[Source]

    # File tangerine.rb, line 24
24:   def initialize(template, taglib=nil)
25:     super template
26:     
27:     @taglib = taglib
28: 
29:     @uid = (@@uid += 1)
30:     @code = ""
31: 
32:     generate_header
33:     generate_code
34:     generate_footer
35:     compile
36:   end

Public Instance methods

Compile generated code into a Proc.

[Source]

     # File tangerine.rb, line 147
147:   def compile
148:     begin
149:       @template = eval @code, nil, "(tangerine)", 1
150:     rescue SyntaxError
151:       raise
152:         "Internal error during compilation. Please submit a bugreport.\n" << $!
153:     end
154:   end

Return a string to be appended to string in order to return code that performs output escaping.

[Source]

    # File tangerine.rb, line 40
40:   def escaper
41:     ""
42:   end

Expand the template for object by calling given methods and inline code.

[Source]

    # File tangerine.rb, line 45
45:   def expand(object)
46:     begin
47:       @template.call object
48:     rescue => exception
49:       raise exception.exception("During template expansion:\n" <<
50:         "    #{exception}\n" <<
51:         "    #{Tangerine.indent 4, exception.backtrace.join("\n")}\n")
52:     end
53:   end

Parse the template and generate appropriate output code.

[Source]

     # File tangerine.rb, line 66
 66:   def generate_code
 67:     @cursor = 0
 68:     @mark = 0
 69:     
 70:     while @cursor = index(',,', @cursor)
 71:       # Skip second comma.
 72:       skip
 73: 
 74:       # Do comma escaping?
 75:       if peek == ?,
 76:         skip  while peek && peek == ?,
 77:         emit_text selection
 78:         @mark = @cursor
 79:         next
 80:       else
 81:         emit_text selection
 82:       end
 83: 
 84:       # Skip comment?
 85:       if peek == ?#
 86:         @mark = @cursor = index("\n", @cursor) + 1
 87:         emit_code "\n"          # Keep lineno uptodate.
 88:         next
 89:       end
 90: 
 91:       # Initialize local variables.
 92:       method = ""
 93:       resolve = false
 94:       indent = get_indentation
 95:       escape = get_escape
 96: 
 97:       case peek
 98:       when ?@
 99:         # Use taglib ...
100:         skip
101:         resolve = true
102:         tag = get_tag
103:         raise 'Tag not resolvable: foo'  unless @taglib
104:         expansion = @taglib.resolve(tag)
105:       when ?(
106:         # ... or instance_eval ...
107:         skip
108:         method = read_to '('[0], ')'[0]
109:       when ?[
110:         # Use instance_eval + refhack
111:         skip
112:         method = "self" + read_to('['[0], ']'[0])
113:       else
114:         # ... or send?
115:         method = get_tag
116:       end
117: 
118:       # Read block?
119:       block = read_block
120: 
121:       skip
122: 
123:       if resolve
124:         emit_code "#{result_variable} = " + self.class.new(expansion, @taglib).code + ".call(#{object_variable}); ";
125:       elsif method =~ /^[\w_]+[!?]?$/
126:         emit_code "#{result_variable} = #{object_variable}.#{method}; "
127:       else
128:         emit_code "#{result_variable} = #{object_variable}.instance_eval(#{method.dump}); "
129:       end
130:       
131:       if block
132:         emit_code "#{template_variable} = " + self.class.new(block).code
133:         emit_code "; #{indent}(#{result_variable} && [*#{result_variable}].map { |d| #{text_variable} << #{template_variable}.call(d) }).to_s#{escape}); "
134:       else
135:         emit_code "#{text_variable} << #{indent}#{result_variable}.to_s#{escape}); "
136:       end
137: 
138:       @mark = @cursor
139:     end
140:     
141:     @cursor = -1  if @cursor.nil?
142: 
143:     emit_text selection_to_end
144:   end

Emit the code footer.

[Source]

    # File tangerine.rb, line 61
61:   def generate_footer
62:     emit_code "#{text_variable} }"
63:   end

Emit the code header.

[Source]

    # File tangerine.rb, line 56
56:   def generate_header
57:     emit_code "lambda { |#{object_variable}| #{text_variable} = ''; "
58:   end

[Validate]