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.



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

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

Instance Attribute Details

#sourceObject (readonly)

The original text of the template is kept here.



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

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]



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

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.



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

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.



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

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