Class: Macros4Cuke::TemplateEngine

Inherits:
Object
  • Object
show all
Defined in:
lib/macros4cuke/template-engine.rb

Overview

A very simple implementation of a templating engine.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(aSourceTemplate) ⇒ TemplateEngine

Constructor.

aSourceTemplate

the template source text. It may contain zero or tags enclosed between chevrons <…>.



63
64
65
66
# File 'lib/macros4cuke/template-engine.rb', line 63

def initialize(aSourceTemplate)
  @source = aSourceTemplate
  @representation = compile(aSourceTemplate)
end

Instance Attribute Details

#sourceObject (readonly)

The original text of the template is kept here.



59
60
61
# File 'lib/macros4cuke/template-engine.rb', line 59

def source
  @source
end

Class Method Details

.parse(aTextLine) ⇒ Object

Class method. Parse the given line text. Returns an array of couples. Couples are of the form:

:static, text

or [:dynamic, text]



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/macros4cuke/template-engine.rb', line 97

def self.parse(aTextLine)
  scanner = StringScanner.new(aTextLine)
  result = []
  
  until scanner.eos?
    # Scan tag at current position...
    tag_literal = scanner.scan(/<(?:[^\\<>]|\\.)*>/)
    result << [:dynamic, tag_literal.gsub(/^<|>$/, '')] unless tag_literal.nil?
    
    # ... or scan plain text at current position
    text_literal = scanner.scan(/(?:[^\\<>]|\\.)+/)
    result << [:static, text_literal] unless text_literal.nil?
    
    if tag_literal.nil? && text_literal.nil?
      # Unsuccessful scanning: we have improperly balanced chevrons.
      # We will analyze the opening and closing chevrons...
      no_escaped = aTextLine.gsub(/\\[<>]/, "--")  # First: replace escaped chevron(s)
      unbalance = 0 # = count of < -  count of > (can only be 0 or -temporarily- 1)

      no_escaped.scan(/(.)/) do |match|
        case match[0]
          when '<'
            unbalance += 1 
          when '>'  
            unbalance -= 1              
        end
        
        raise StandardError, "Nested opening chevron '<'." if unbalance > 1
        raise StandardError, "Missing opening chevron '<'." if unbalance < 0
      end
      
      raise StandardError, "Missing closing chevron '>'." if unbalance == 1
      raise StandardError, "Cannot parse:\n'#{aTextLine}'"
    end
  end
  
  return result
end

Instance Method Details

#render(aContextObject = nil, theLocals) ⇒ Object

aContextObject

context object to get actual values (when not present in the Hash parameter).

theLocals

a Hash with pairs of the form: argument name => actual value.



71
72
73
74
75
76
77
78
79
80
# File 'lib/macros4cuke/template-engine.rb', line 71

def render(aContextObject = nil, theLocals)
  return '' if @representation.empty?
  context = aContextObject.nil? ? Object.new : aContextObject
  
  result = @representation.each_with_object('') do |element, subResult|
    subResult << element.render(context, theLocals)
  end
  
  return result
end

#variablesObject

Return all variable names that appear in the template.



83
84
85
86
87
88
89
90
91
# File 'lib/macros4cuke/template-engine.rb', line 83

def variables()
  # The result will be cached/memoized...
  @variables ||= begin
    vars = @representation.select { |element| element.is_a?(VariableRep) }
    vars.map(&:name)
  end
  
  return @variables
end