Class Haml::Engine

  1. lib/haml/engine.rb
Parent: Object

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

Methods

public class

  1. new

public instance

  1. def_method
  2. html4?
  3. html5?
  4. html?
  5. render
  6. render_proc
  7. to_html
  8. xhtml?

Included modules

  1. Precompiler

Public class methods

new (template, options = {})

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.

[show source]
    # File lib/haml/engine.rb, line 55
55:     def initialize(template, options = {})
56:       @options = {
57:         :suppress_eval => false,
58:         :attr_wrapper => "'",
59: 
60:         # Don't forget to update the docs in lib/haml.rb if you update these
61:         :autoclose => %w[meta img link br hr input area param col base],
62:         :preserve => %w[textarea pre],
63: 
64:         :filename => '(haml)',
65:         :line => 1,
66:         :ugly => false,
67:         :format => :xhtml,
68:         :escape_html => false
69:       }
70:       @options.merge! options
71: 
72:       unless [:xhtml, :html4, :html5].include?(@options[:format])
73:         raise Haml::Error, "Invalid format #{@options[:format].inspect}"
74:       end
75: 
76:       @template = template.rstrip + "\n-#\n-#"
77:       @to_close_stack = []
78:       @output_tabs = 0
79:       @template_tabs = 0
80:       @index = 0
81:       @flat_spaces = -1
82:       @newlines = 0
83:       @precompiled = ''
84:       @merged_text = ''
85:       @tab_change  = 0
86: 
87:       if @template =~ /\A(\s*\n)*[ \t]+\S/
88:         raise SyntaxError.new("Indenting at the beginning of the document is illegal.", ($1 || "").count("\n"))
89:       end
90: 
91:       if @options[:filters]
92:         warn "DEPRECATION WARNING:\nThe Haml :filters option is deprecated and will be removed in version 2.1.\nFilters are now automatically registered.\n"
93:       end
94: 
95:       precompile
96:     rescue Haml::Error => e
97:       e.backtrace.unshift "#{@options[:filename]}:#{(e.line ? e.line + 1 : @index) + @options[:line] - 1}" if @index
98:       raise
99:     end

Public instance methods

def_method (object, name, *local_names)

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").

[show source]
     # File lib/haml/engine.rb, line 238
238:     def def_method(object, name, *local_names)
239:       method = object.is_a?(Module) ? :module_eval : :instance_eval
240: 
241:       object.send(method, "def #{name}(_haml_locals = {}); #{precompiled_with_ambles(local_names)}; end",
242:                   @options[:filename], @options[:line])
243:     end
html4? ()

True if the format is HTML4

[show source]
    # File lib/haml/engine.rb, line 37
37:     def html4?
38:       @options[:format] == :html4
39:     end
html5? ()

True if the format is HTML5

[show source]
    # File lib/haml/engine.rb, line 42
42:     def html5?
43:       @options[:format] == :html5
44:     end
html? ()

True if the format is any flavor of HTML

[show source]
    # File lib/haml/engine.rb, line 32
32:     def html?
33:       html4? or html5?
34:     end
render (scope = Object.new, locals = {}, &block)

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.

[show source]
     # File lib/haml/engine.rb, line 141
141:     def render(scope = Object.new, locals = {}, &block)
142:       buffer = Haml::Buffer.new(scope.instance_variable_get('@haml_buffer'), options_for_buffer)
143: 
144:       if scope.is_a?(Binding) || scope.is_a?(Proc)
145:         scope_object = eval("self", scope)
146:         scope = scope_object.instance_eval{binding} if block_given?
147:       else
148:         scope_object = scope
149:         scope = scope_object.instance_eval{binding}
150:       end
151: 
152:       set_locals(locals.merge(:_hamlout => buffer, :_erbout => buffer.buffer), scope, scope_object)
153: 
154:       scope_object.instance_eval do
155:         extend Haml::Helpers
156:         @haml_buffer = buffer
157:       end
158: 
159:       eval(@precompiled, scope, @options[:filename], @options[:line])
160: 
161:       # Get rid of the current buffer
162:       scope_object.instance_eval do
163:         @haml_buffer = buffer.upper
164:       end
165: 
166:       buffer.buffer
167:     end
render_proc (scope = Object.new, *local_names)

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.

[show source]
     # File lib/haml/engine.rb, line 191
191:     def render_proc(scope = Object.new, *local_names)
192:       if scope.is_a?(Binding) || scope.is_a?(Proc)
193:         scope_object = eval("self", scope)
194:       else
195:         scope_object = scope
196:         scope = scope_object.instance_eval{binding}
197:       end
198: 
199:       eval("Proc.new { |*_haml_locals| _haml_locals = _haml_locals[0] || {};" +
200:            precompiled_with_ambles(local_names) + "}\n", scope, @options[:filename], @options[:line])
201:     end
to_html (scope = Object.new, locals = {}, &block)

Alias for render

xhtml? ()

True if the format is XHTML

[show source]
    # File lib/haml/engine.rb, line 27
27:     def xhtml?
28:       not html?
29:     end