class Haml::Engine
puts output
output = haml_engine.to_html
haml_engine = Haml::Engine.new(template)
template = File.read(‘templates/really_cool_template.haml’)
new instance and calling to_html
to render the template. For example:
template is done. It can be directly used by the user by creating a
This is the class where all the parsing and processing of the Haml
def def_method(object, name, *local_names)
It extends Haml::Helpers, and various instance variables are set
(either the scope object or the "self" object of the scope binding).
Note that Haml modifies the evaluation context
obj.render(:foo => "Hello!") #=> NameError: undefined local variable or method `foo'
Haml::Engine.new("%p= foo").def_method(obj, :render)
obj = Object.new
# This doesn't
obj.render(:foo => "Hello!") #=> "
Hello!
"Haml::Engine.new("%p= foo").def_method(obj, :render, :foo)
obj = Object.new
# This works
For example:
This is done with the +local_names+ argument.
the local variables which can be assigned must be pre-declared.
However, due to an unfortunate Ruby quirk,
The first argument of the defined method is a hash of local variable names to values.
"foobar".upcased_div #=> "
FOOBAR
\n"Haml::Engine.new(".upcased= upcase").def_method(String, :upcased_div)
t.render #=> "
\n Today's date is\n
Fri Nov 23 18:28:29 -0800 2007
\n\n"Haml::Engine.new("%p\n Today's date is\n .date= self.to_s").def_method(t, :render)
t = Time.now
For example:
the method will instead by defined as an instance method.
If +object+ is a class or module,
that renders the template and returns the result as a string.
with the given name
Defines a method on +object+
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
def html4?
def html4? @options[:format] == :html4 end
def html5?
def html5? @options[:format] == :html5 end
def html?
def html? html4? or html5? end
def initialize(template, options = {})
++
to lib/haml.rb!
When adding options, remember to add information about them
--
See the Haml module documentation for available options.
template string when render is called.
Creates a new instace of Haml::Engine that will compile the given
def initialize(template, options = {}) @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! options unless [:xhtml, :html4, :html5].include?(@options[:format]) raise Haml::Error, "Invalid format #{@options[:format].inspect}" end @template = template.rstrip + "\n-#\n-#" @to_close_stack = [] @output_tabs = 0 @template_tabs = 0 @index = 0 @flat_spaces = -1 @newlines = 0 @precompiled = '' @merged_text = '' @tab_change = 0 if @template =~ /\A(\s*\n)*[ \t]+\S/ raise SyntaxError.new("Indenting at the beginning of the document is illegal.", ($1 || "").count("\n")) end if @options[:filters] warn <<END ECATION WARNING: Haml :filters option is deprecated and will be removed in version 2.1. ers are now automatically registered. end precompile rescue Haml::Error => e e.backtrace.unshift "#{@options[:filename]}:#{(e.line ? e.line + 1 : @index) + @options[:line] - 1}" if @index raise end
def options_for_buffer
Returns a hash of options that Haml::Buffer cares about.
def options_for_buffer { :autoclose => @options[:autoclose], :preserve => @options[:preserve], :attr_wrapper => @options[:attr_wrapper], :ugly => @options[:ugly], :format => @options[:format] } end
def render(scope = Object.new, locals = {}, &block)
but if you're relying on local variables defined in the context of scope,
This won't have an effect in most cases,
In particular, it's equivalent to passing eval("self", scope) as scope.
the evaluation context may not be quite what the user expects.
if scope is a Binding or Proc object and a block is given,
Due to some Ruby quirks,
within the template.
that block is run when +yield+ is called
If a block is passed to render,
Haml::Engine.new("%p= foo").render(Object.new, :foo => "Hello, world!") #=> "
Hello, world!
"For example:
+locals+ is a hash of local variables to make available to the template.
s.responds_to?(:html_attrs) #=> true
# s now extends Haml::Helpers
Haml::Engine.new("%p= upcase").render(s) #=> "
FOOBAR
"s = "foobar"
For example:
(all prefixed with "haml").
It extends Haml::Helpers, and various instance variables are set
(either the scope object or the "self" object of the scope binding).
Note that Haml modifies the evaluation context
otherwise, Haml just uses its #instance_eval context.
Haml uses it as the second argument to Kernel#eval;
If it's a Binding or Proc object,
+scope+ is the context in which the template is evaluated.
Processes the template and returns the result as a string.
def render(scope = Object.new, locals = {}, &block) buffer = Haml::Buffer.new(scope.instance_variable_get('@haml_buffer'), options_for_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
def render_proc(scope = Object.new, *local_names)
The proc doesn't take a block;
#=> NameError: undefined local variable or method `foo'
Haml::Engine.new("%p= foo").render_proc.call :foo => "Hello!"
# This doesn't
#=> "
Hello!
"Haml::Engine.new("%p= foo").render_proc(Object.new, :foo).call :foo => "Hello!"
# This works
For example:
This is done with the +local_names+ argument.
the local variables which can be assigned must be pre-declared.
However, due to an unfortunate Ruby quirk,
The first argument of the returned proc is a hash of local variable names to values.
+scope+ works the same as it does for render.
renders the template and returns the result as a string.
Returns a proc that, when called,
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
def set_locals(locals, scope, scope_object)
def set_locals(locals, scope, scope_object) scope_object.send(:instance_variable_set, '@_haml_locals', locals) set_locals = locals.keys.map { |k| "#{k} = @_haml_locals[#{k.inspect}]" }.join("\n") eval(set_locals, scope) end
def xhtml?
def xhtml? not html? end