Class: Macros4Cuke::Templating::Engine
- Inherits:
-
Object
- Object
- Macros4Cuke::Templating::Engine
- Defined in:
- lib/macros4cuke/templating/engine.rb
Overview
- 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
-
#representation ⇒ Object
readonly
The internal representation of the template text.
-
#source ⇒ Object
readonly
The original text of the template is kept here.
Class Method Summary collapse
-
.identify_parse_error(aTextLine) ⇒ Object
Called when the given text line could not be parsed.
-
.parse(aTextLine) ⇒ Array
Class method.
Instance Method Summary collapse
-
#initialize(aSourceTemplate) ⇒ Engine
constructor
Builds an Engine and compiles the given template text into an internal representation.
-
#render(aContextObject = Object.new, theLocals = {}) ⇒ String
Render the template within the given scope object and with the locals specified.
-
#variables ⇒ Array
Retrieve all placeholder names that appear in the template.
Constructor Details
#initialize(aSourceTemplate) ⇒ Engine
Builds an Engine and compiles the given template text into an internal representation.
54 55 56 57 |
# File 'lib/macros4cuke/templating/engine.rb', line 54 def initialize(aSourceTemplate) @source = aSourceTemplate @representation = compile(aSourceTemplate) end |
Instance Attribute Details
#representation ⇒ Object (readonly)
The internal representation of the template text
48 49 50 |
# File 'lib/macros4cuke/templating/engine.rb', line 48 def representation @representation end |
#source ⇒ Object (readonly)
The original text of the template is kept here.
45 46 47 |
# File 'lib/macros4cuke/templating/engine.rb', line 45 def source @source end |
Class Method Details
.identify_parse_error(aTextLine) ⇒ Object
Called when the given text line could not be parsed. Raises an exception with the syntax issue identified.
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/macros4cuke/templating/engine.rb', line 137 def self.identify_parse_error(aTextLine) # Unsuccessful scanning: we typically have improperly balanced chevrons. # We will analyze the opening and closing chevrons... # First: replace escaped chevron(s) no_escaped = aTextLine.gsub(/\\[<>]/, '--') # var. equals count_of(<) - count_of(>): can only be 0 or temporarily 1 unbalance = 0 no_escaped.each_char do |ch| case ch when '<' then unbalance += 1 when '>' then unbalance -= 1 end suffix = "opening chevron '<'." raise(StandardError, 'Nested ' + suffix) if unbalance > 1 raise(StandardError, 'Missing ' + suffix) if unbalance.negative? end raise(StandardError, "Missing closing chevron '>'.") if unbalance == 1 end |
.parse(aTextLine) ⇒ Array
Class method. Parse the given line text into a raw representation. [:static, text], [:comment, text] or [:dynamic, tag text]
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/macros4cuke/templating/engine.rb', line 110 def self.parse(aTextLine) scanner = StringScanner.new(aTextLine) result = [] if scanner.check(/\s*#/) # Detect comment line result << [:comment, aTextLine] else 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 literal = scanner.scan(/(?:[^\\<>]|\\.)+/) result << [:static, literal] unless literal.nil? identify_parse_error(aTextLine) if tag_literal.nil? && literal.nil? end 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.
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/macros4cuke/templating/engine.rb', line 68 def render(aContextObject = Object.new, theLocals = {}) return '' if @representation.empty? prev = nil result = @representation.each_with_object(+'') do |element, subResult| # Output compaction rules: # -In case of consecutive eol's only one is rendered. # -In case of comment followed by one eol, both aren't rendered unless element.is_a?(EOLine) && (prev.is_a?(EOLine) || prev.is_a?(Comment)) subResult << element.render(aContextObject, theLocals) end prev = element end return result end |
#variables ⇒ Array
Retrieve all placeholder names that appear in the template.
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/macros4cuke/templating/engine.rb', line 88 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) end end vars.flatten.uniq end return @variables end |