Class: Macros4Cuke::Templating::Engine

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

Overview

A very simple implementation of a templating engine.
Earlier versions of Macros4Cuke relied on the logic-less Mustache template engine.
But it was decided afterwards to replace it by a very simple template engine.
The reasons were the following:

  • Be closer to the usual Gherkin syntax (parameters of scenario outlines use chevrons <...>, while Mustache use {{...}} delimiters),
  • Feature files are meant to be simple, so should the template engine be.

Constant Summary collapse

DisallowedSigns =

The regular expression that matches a space, any punctuation sign or delimiter that is forbidden between chevrons <...> template tags.

begin 
  # Use concatenation (+) to work around Ruby bug!
  forbidden =  ' !"#' + "$%&'()*+,-./:;<=>?[\\]^`{|}~" 
  all_escaped = [] 
  forbidden.each_char() { |ch| all_escaped << Regexp.escape(ch) }
  pattern = all_escaped.join('|')
  Regexp.new(pattern)
end

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(aSourceTemplate) ⇒ Engine

Builds an Engine and compiles the given template text into an internal representation.



247
248
249
250
# File 'lib/macros4cuke/templating/engine.rb', line 247

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

Instance Attribute Details

#sourceObject (readonly)

The original text of the template is kept here.



241
242
243
# File 'lib/macros4cuke/templating/engine.rb', line 241

def source
  @source
end

Class Method Details

.parse(aTextLine) ⇒ Array

Class method. Parse the given line text into a raw representation. [:static, text] or [:dynamic, tag text]



300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
# File 'lib/macros4cuke/templating/engine.rb', line 300

def self.parse(aTextLine)
  scanner = StringScanner.new(aTextLine)
  result = []
  
  until scanner.eos?
    # Scan tag at current position...
    tag_literal = scanner.scan(/<(?:[^\\<>]|\\.)*>/)
    unless tag_literal.nil?
      result << [:dynamic, tag_literal.gsub(/^<|>$/, '')] 
    end
    
    # ... or scan plain text at current position
    text_literal = scanner.scan(/(?:[^\\<>]|\\.)+/)
    result << [:static, text_literal] unless text_literal.nil? 
    identify_parse_error(aTextLine) if tag_literal.nil? && text_literal.nil?
  end
  
  return result
end

Instance Method Details

#render(aContextObject = Object.new, theLocals) ⇒ String

Render the template within the given scope object and with the locals specified. The method mimicks the signature of the Tilt::Template#render method.



262
263
264
265
266
267
268
269
270
# File 'lib/macros4cuke/templating/engine.rb', line 262

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

#variablesArray

Retrieve all placeholder names that appear in the template.



275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
# File 'lib/macros4cuke/templating/engine.rb', line 275

def variables()
  # The result will be cached/memoized...
  @variables ||= begin
    vars = @representation.each_with_object([]) do |element, subResult|
      case element
        when Placeholder          
          subResult << element.name
        
        when Section
          subResult.concat(element.variables)
        
        else
          # Do nothing
      end
    end
    
    vars.flatten.uniq
  end
  
  return @variables
end