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.

Parameters:

  • aSourceTemplate (String)

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



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]

Returns:

  • (Array)

    Couples of the form:



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.

Parameters:

  • aContextObject (anything) (defaults to: Object.new)

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

  • theLocals (Hash)

    Contains one or more pairs of the form: tag/placeholder name => actual value.

Returns:

  • (String)

    The rendition of the template given the passed argument values.



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.

Returns:

  • (Array)

    The list of placeholder names.



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