Class: Haml::Engine
Overview
This is the class where all the parsing and processing of the Haml template is done. It can be directly used by the user by creating a new instance and calling to_html
to render the template. For example:
template = File.read('templates/really_cool_template.haml')
haml_engine = Haml::Engine.new(template)
output = haml_engine.to_html
puts output
Constant Summary
Constants included from Precompiler
Precompiler::COMMENT, Precompiler::DIV_CLASS, Precompiler::DIV_ID, Precompiler::DOCTYPE_OR_UNESCAPE, Precompiler::DOCTYPE_REGEX, Precompiler::ELEMENT, Precompiler::ESCAPE, Precompiler::FILTER, Precompiler::FLAT_SCRIPT, Precompiler::LITERAL_VALUE_REGEX, Precompiler::MID_BLOCK_KEYWORDS, Precompiler::MULTILINE_CHAR_VALUE, Precompiler::PLAIN_TEXT, Precompiler::SANITIZE, Precompiler::SCRIPT, Precompiler::SILENT_COMMENT, Precompiler::SILENT_SCRIPT, Precompiler::SPECIAL_CHARACTERS
Constants included from Util
Instance Attribute Summary collapse
-
#indentation ⇒ Object
A string containing the indentation used for the Haml document.
-
#options ⇒ Object
Allow reading and writing of the options hash.
-
#precompiled ⇒ Object
This string contains the source code that is evaluated to produce the Haml document.
Instance Method Summary collapse
-
#def_method(object, name, *local_names) ⇒ Object
Defines a method on
object
with the given name that renders the template and returns the result as a string. -
#html4? ⇒ Boolean
True if the format is HTML4.
-
#html5? ⇒ Boolean
True if the format is HTML5.
-
#html? ⇒ Boolean
True if the format is any flavor of HTML.
-
#initialize(template, options = {}) ⇒ Engine
constructor
Creates a new instace of Haml::Engine that will compile the given template string when
render
is called. -
#render(scope = Object.new, locals = {}, &block) ⇒ Object
(also: #to_html)
Processes the template and returns the result as a string.
-
#render_proc(scope = Object.new, *local_names) ⇒ Object
Returns a proc that, when called, renders the template and returns the result as a string.
-
#xhtml? ⇒ Boolean
True if the format is XHTML.
Methods included from Util
#def_static_method, #enum_with_index, #has?, #map_hash, #map_keys, #map_vals, #powerset, #ruby1_8?, #static_method_name, #to_hash
Constructor Details
#initialize(template, options = {}) ⇒ Engine
Creates a new instace of Haml::Engine that will compile the given template string when render
is called. See the Haml module documentation for available options.
– When adding options, remember to add information about them to lib/haml.rb! ++
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/haml/engine.rb', line 60 def initialize(template, = {}) @options = { :suppress_eval => false, :attr_wrapper => "'", # Don't forget to update the docs in lib/haml.rb if you update these :autoclose => %w[meta img link br hr input area param col base], :preserve => %w[textarea pre], :filename => '(haml)', :line => 1, :ugly => false, :format => :xhtml, :escape_html => false } @options.merge! @index = 0 unless [:xhtml, :html4, :html5].include?(@options[:format]) raise Haml::Error, "Invalid format #{@options[:format].inspect}" end # :eod is a special end-of-document marker @template = (template.rstrip).split(/\r\n|\r|\n/) + [:eod, :eod] @template_index = 0 @to_close_stack = [] @output_tabs = 0 @template_tabs = 0 @flat = false @newlines = 0 @precompiled = '' @to_merge = [] @tab_change = 0 @temp_count = 0 if @options[:filters] warn <<END DEPRECATION WARNING: The Haml :filters option is deprecated and will be removed in version 2.2. Filters are now automatically registered. END end precompile rescue Haml::Error => e e.backtrace.unshift "#{@options[:filename]}:#{(e.line ? e.line + 1 : @index) + @options[:line] - 1}" if @index raise end |
Instance Attribute Details
#indentation ⇒ Object
A string containing the indentation used for the Haml document. nil if the indentation is ambiguous (for example, for a single-level document).
29 30 31 |
# File 'lib/haml/engine.rb', line 29 def indentation @indentation end |
#options ⇒ Object
Allow reading and writing of the options hash
20 21 22 |
# File 'lib/haml/engine.rb', line 20 def @options end |
#precompiled ⇒ Object
This string contains the source code that is evaluated to produce the Haml document.
24 25 26 |
# File 'lib/haml/engine.rb', line 24 def precompiled @precompiled end |
Instance Method Details
#def_method(object, name, *local_names) ⇒ Object
Defines a method on object
with the given name that renders the template and returns the result as a string.
If object
is a class or module, the method will instead by defined as an instance method. For example:
t = Time.now
Haml::Engine.new("%p\n Today's date is\n .date= self.to_s").def_method(t, :render)
t.render #=> "<p>\n Today's date is\n <div class='date'>Fri Nov 23 18:28:29 -0800 2007</div>\n</p>\n"
Haml::Engine.new(".upcased= upcase").def_method(String, :upcased_div)
"foobar".upcased_div #=> "<div class='upcased'>FOOBAR</div>\n"
The first argument of the defined method is a hash of local variable names to values. However, due to an unfortunate Ruby quirk, the local variables which can be assigned must be pre-declared. This is done with the local_names
argument. For example:
# This works
obj = Object.new
Haml::Engine.new("%p= foo").def_method(obj, :render, :foo)
obj.render(:foo => "Hello!") #=> "<p>Hello!</p>"
# This doesn't
obj = Object.new
Haml::Engine.new("%p= foo").def_method(obj, :render)
obj.render(:foo => "Hello!") #=> NameError: undefined local variable or method `foo'
Note that Haml modifies the evaluation context (either the scope object or the “self” object of the scope binding). It extends Haml::Helpers, and various instance variables are set (all prefixed with “haml”).
241 242 243 244 245 246 |
# File 'lib/haml/engine.rb', line 241 def def_method(object, name, *local_names) method = object.is_a?(Module) ? :module_eval : :instance_eval object.send(method, "def #{name}(_haml_locals = {}); #{precompiled_with_ambles(local_names)}; end", @options[:filename], @options[:line]) end |
#html4? ⇒ Boolean
True if the format is HTML4
42 43 44 |
# File 'lib/haml/engine.rb', line 42 def html4? @options[:format] == :html4 end |
#html5? ⇒ Boolean
True if the format is HTML5
47 48 49 |
# File 'lib/haml/engine.rb', line 47 def html5? @options[:format] == :html5 end |
#html? ⇒ Boolean
True if the format is any flavor of HTML
37 38 39 |
# File 'lib/haml/engine.rb', line 37 def html? html4? or html5? end |
#render(scope = Object.new, locals = {}, &block) ⇒ Object Also known as: to_html
Processes the template and returns the result as a string.
scope
is the context in which the template is evaluated. If it’s a Binding or Proc object, Haml uses it as the second argument to Kernel#eval; otherwise, Haml just uses its #instance_eval context.
Note that Haml modifies the evaluation context (either the scope object or the “self” object of the scope binding). It extends Haml::Helpers, and various instance variables are set (all prefixed with “haml”). For example:
s = "foobar"
Haml::Engine.new("%p= upcase").render(s) #=> "<p>FOOBAR</p>"
# s now extends Haml::Helpers
s.responds_to?(:html_attrs) #=> true
locals
is a hash of local variables to make available to the template. For example:
Haml::Engine.new("%p= foo").render(Object.new, :foo => "Hello, world!") #=> "<p>Hello, world!</p>"
If a block is passed to render, that block is run when yield
is called within the template.
Due to some Ruby quirks, if scope is a Binding or Proc object and a block is given, the evaluation context may not be quite what the user expects. In particular, it’s equivalent to passing eval("self", scope)
as scope. This won’t have an effect in most cases, but if you’re relying on local variables defined in the context of scope, they won’t work.
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/haml/engine.rb', line 144 def render(scope = Object.new, locals = {}, &block) buffer = Haml::Buffer.new(scope.instance_variable_get('@haml_buffer'), ) if scope.is_a?(Binding) || scope.is_a?(Proc) scope_object = eval("self", scope) scope = scope_object.instance_eval{binding} if block_given? else scope_object = scope scope = scope_object.instance_eval{binding} end set_locals(locals.merge(:_hamlout => buffer, :_erbout => buffer.buffer), scope, scope_object) scope_object.instance_eval do extend Haml::Helpers @haml_buffer = buffer end eval(@precompiled, scope, @options[:filename], @options[:line]) # Get rid of the current buffer scope_object.instance_eval do @haml_buffer = buffer.upper end buffer.buffer end |
#render_proc(scope = Object.new, *local_names) ⇒ Object
Returns a proc that, when called, renders the template and returns the result as a string.
scope
works the same as it does for render.
The first argument of the returned proc is a hash of local variable names to values. However, due to an unfortunate Ruby quirk, the local variables which can be assigned must be pre-declared. This is done with the local_names
argument. For example:
# This works
Haml::Engine.new("%p= foo").render_proc(Object.new, :foo).call :foo => "Hello!"
#=> "<p>Hello!</p>"
# This doesn't
Haml::Engine.new("%p= foo").render_proc.call :foo => "Hello!"
#=> NameError: undefined local variable or method `foo'
The proc doesn’t take a block; any yields in the template will fail.
194 195 196 197 198 199 200 201 202 203 204 |
# File 'lib/haml/engine.rb', line 194 def render_proc(scope = Object.new, *local_names) if scope.is_a?(Binding) || scope.is_a?(Proc) scope_object = eval("self", scope) else scope_object = scope scope = scope_object.instance_eval{binding} end eval("Proc.new { |*_haml_locals| _haml_locals = _haml_locals[0] || {};" + precompiled_with_ambles(local_names) + "}\n", scope, @options[:filename], @options[:line]) end |
#xhtml? ⇒ Boolean
True if the format is XHTML
32 33 34 |
# File 'lib/haml/engine.rb', line 32 def xhtml? not html? end |