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.
52 53 54 55 |
# File 'lib/macros4cuke/templating/engine.rb', line 52 def initialize(aSourceTemplate) @source = aSourceTemplate @representation = compile(aSourceTemplate) end |
Instance Attribute Details
#representation ⇒ Object (readonly)
The internal representation of the template text
46 47 48 |
# File 'lib/macros4cuke/templating/engine.rb', line 46 def representation @representation end |
#source ⇒ Object (readonly)
The original text of the template is kept here.
43 44 45 |
# File 'lib/macros4cuke/templating/engine.rb', line 43 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.
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/macros4cuke/templating/engine.rb', line 136 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 raise(StandardError, "Nested opening chevron '<'.") if unbalance > 1 raise(StandardError, "Missing opening chevron '<'.") if unbalance < 0 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]
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/macros4cuke/templating/engine.rb', line 109 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.
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/macros4cuke/templating/engine.rb', line 66 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.
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/macros4cuke/templating/engine.rb', line 87 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 |