lib/macros4cuke/templating/engine.rb in macros4cuke-0.4.02 vs lib/macros4cuke/templating/engine.rb in macros4cuke-0.4.03

- old
+ new

@@ -1,12 +1,16 @@ # File: engine.rb -# Purpose: Implementation of the MacroStep class. +# Purpose: Implementation of the Engine class. require 'strscan' # Use the StringScanner for lexical analysis. require_relative '../exceptions' # Load the custom exception classes. +require_relative 'template-element' +require_relative 'placeholder' +require_relative 'section' # Load the Section and ConditionalSection + module Macros4Cuke # Module used as a namespace # Module containing all classes implementing the simple template engine # used internally in Macros4Cuke. @@ -78,173 +82,9 @@ def render(aContextObject, theLocals) return "\n" end end # class - -# Base class used internally by the template engine. -# The generalization of any element from a template that has one variable -# whose actual value influences the rendition. -class UnaryElement - # The name of the placeholder/variable. - attr_reader(:name) - - # @param aVarName [String] The name of the placeholder from a template. - def initialize(aVarName) - @name = aVarName - end - - protected - - # This method has the same signature as the {Engine#render} method. - # @return [Object] The actual value from the locals or context - # that is assigned to the variable. - def retrieve_value_from(aContextObject, theLocals) - actual_value = theLocals[name] - if actual_value.nil? && aContextObject.respond_to?(name.to_sym) - actual_value = aContextObject.send(name.to_sym) - end - - return actual_value - end - -end # class - - - -# Class used internally by the template engine. -# Represents a named placeholder in a template, that is, -# a name placed between <..> in the template. -# At rendition, a placeholder is replaced by the text value -# that is associated with it. -class Placeholder < UnaryElement - - public - - # Render the placeholder given the passed arguments. - # This method has the same signature as the {Engine#render} method. - # @return [String] The text value assigned to the placeholder. - # Returns an empty string when no value is assigned to the placeholder. - def render(aContextObject, theLocals) - actual_value = retrieve_value_from(aContextObject, theLocals) - - result = case actual_value - when NilClass - '' - - when Array - # TODO: Move away from hard-coded separator. - actual_value.join('<br/>') - - when String - actual_value - else - actual_value.to_s - end - - return result - end - -end # class - - -# Base class used internally by the template engine. -# Represents a section in a template, that is, -# a set of template elements for which its rendition depends -# on the value of a variable. -class Section < UnaryElement - # The child elements of the section - attr_reader(:children) - - # @param aVarName [String] The name of the placeholder from a template. - def initialize(aVarName) - super(aVarName) - @children = [] - end - - public - - # Add a child element as member of the section - def add_child(aChild) - children << aChild - end - - # Retrieve all placeholder names that appear in the template. - # @return [Array] The list of placeholder names. - def variables() - all_vars = children.each_with_object([]) do |a_child, subResult| - case a_child - when Placeholder - subResult << a_child.name - when Section - subResult.concat(a_child.variables) - else - # Do nothing - end - end - - return all_vars.flatten.uniq - end - - - # Render the placeholder given the passed arguments. - # This method has the same signature as the {Engine#render} method. - # @return [String] The text value assigned to the placeholder. - # Returns an empty string when no value is assigned to the placeholder. - def render(aContextObject, theLocals) - msg = "Method Section.#{__method__} must be implemented in subclass." - fail(NotImplementedError, msg) - end - -end # class - - -# A specialized section in a template for which its rendition -# depends on the (in)existence of an actual value bound to the variable name. -class ConditionalSection < Section - # A boolean that indicates whether the rendition condition is - # the existence of a value for the variable (true) - # or its inexistence (false). - attr_reader(:existence) - - # @param aVarName [String] The name of the placeholder from a template. - # @param renderWhenExisting [boolean] When true, render the children elements - # if a value exists for the variable. - def initialize(aVarName, renderWhenExisting = true) - super(aVarName) - @existence = renderWhenExisting - end - - public - - # Render the placeholder given the passed arguments. - # This method has the same signature as the {Engine#render} method. - # @return [String] The text value assigned to the placeholder. - # Returns an empty string when no value is assigned to the placeholder. - def render(aContextObject, theLocals) - actual_value = retrieve_value_from(aContextObject, theLocals) - if (!actual_value.nil? && existence) || (actual_value.nil? && !existence) - # Let render the children - result = children.each_with_object('') do |a_child, sub_result| - sub_result << a_child.render(aContextObject, theLocals) - end - else - result = '' - end - - return result - end - - - # @return [String] The original text representation of the tag. - def to_s() - return "<?#{name}>" - end - -end # class - - -SectionEndMarker = Struct.new(:name) # A very simple implementation of a templating engine. # Earlier versions of Macros4Cuke relied on the logic-less # Mustache template engine.