Class: Haml::Engine
Overview
This is the frontend for using Haml programmatically. It can be directly used by the user by creating a new instance and calling #render to render the template. For example:
template = File.read('templates/really_cool_template.haml')
haml_engine = Haml::Engine.new(template)
output = haml_engine.render
puts output
Constant Summary
Constants included from Precompiler
Precompiler::COMMENT, Precompiler::DIV_CLASS, Precompiler::DIV_ID, Precompiler::DOCTYPE, Precompiler::DOCTYPE_REGEX, Precompiler::ELEMENT, Precompiler::ESCAPE, Precompiler::FILTER, Precompiler::FLAT_SCRIPT, Precompiler::LITERAL_VALUE_REGEX, Precompiler::MID_BLOCK_KEYWORD_REGEX, 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 ⇒ String
The indentation used in the Haml document, or
nil
if the indentation is ambiguous (for example, for a single-level document). -
#options ⇒ Hash<Symbol, Object>
The options hash.
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
Whether or not the format is HTML4.
-
#html5? ⇒ Boolean
Whether or not the format is HTML5.
-
#html? ⇒ Boolean
Whether or not the format is any flavor of HTML.
-
#initialize(template, options = {}) ⇒ Engine
constructor
Precompiles the Haml template.
- #options_for_buffer ⇒ Hash<Symbol, Object> protected
-
#precompiled ⇒ String
The source code that is evaluated to produce the Haml document.
-
#render(scope = Object.new, locals = {}, &block) ⇒ String
(also: #to_html)
Processes the template and returns the result as a string.
-
#render_proc(scope = Object.new, *local_names) ⇒ Proc
Returns a proc that, when called, renders the template and returns the result as a string.
-
#xhtml? ⇒ Boolean
Whether or not the format is XHTML.
Methods included from Util
#check_encoding, #def_static_method, #enum_with_index, #has?, #map_hash, #map_keys, #map_vals, #merge_adjacent_strings, #powerset, #ruby1_8?, #scope, #static_method_name, #to_hash
Constructor Details
#initialize(template, options = {}) ⇒ Engine
Precompiles the Haml template.
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 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/haml/engine.rb', line 70
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,
}
unless ruby1_8?
@options[:encoding] = Encoding.default_internal || "utf-8"
end
@options.merge! options
@index = 0
unless [:xhtml, :html4, :html5].include?(@options[:format])
raise Haml::Error, "Invalid format #{@options[:format].inspect}"
end
if @options[:encoding] && @options[:encoding].is_a?(Encoding)
@options[:encoding] = @options[:encoding].name
end
check_encoding(template) {|msg, line| raise Haml::Error.new(msg, line)}
# :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
precompile
rescue Haml::Error => e
if @index || e.line
e.backtrace.unshift "#{@options[:filename]}:#{(e.line ? e.line + 1 : @index) + @options[:line] - 1}"
end
raise
end
|
Instance Attribute Details
#indentation ⇒ String
The indentation used in the Haml document,
or nil
if the indentation is ambiguous
(for example, for a single-level document).
31 32 33 |
# File 'lib/haml/engine.rb', line 31
def indentation
@indentation
end
|
#options ⇒ Hash<Symbol, Object>
The options hash. See the Haml options documentation.
24 25 26 |
# File 'lib/haml/engine.rb', line 24
def options
@options
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 Helpers, and various instance variables are set
(all prefixed with haml_
).
266 267 268 269 270 271 |
# File 'lib/haml/engine.rb', line 266
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
Returns Whether or not the format is HTML4.
44 45 46 |
# File 'lib/haml/engine.rb', line 44
def html4?
@options[:format] == :html4
end
|
#html5? ⇒ Boolean
Returns Whether or not the format is HTML5.
49 50 51 |
# File 'lib/haml/engine.rb', line 49
def html5?
@options[:format] == :html5
end
|
#html? ⇒ Boolean
Returns Whether or not the format is any flavor of HTML.
39 40 41 |
# File 'lib/haml/engine.rb', line 39
def html?
html4? or html5?
end
|
#options_for_buffer ⇒ Hash<Symbol, Object> (protected)
282 283 284 285 286 287 288 289 290 291 |
# File 'lib/haml/engine.rb', line 282
def options_for_buffer
{
:autoclose => @options[:autoclose],
:preserve => @options[:preserve],
:attr_wrapper => @options[:attr_wrapper],
:ugly => @options[:ugly],
:format => @options[:format],
:encoding => @options[:encoding],
}
end
|
#precompiled ⇒ String
The source code that is evaluated to produce the Haml document.
In Ruby 1.9, this is automatically converted to the correct encoding
(see the :encoding
option).
59 60 61 62 |
# File 'lib/haml/engine.rb', line 59
def precompiled
return @precompiled if ruby1_8?
return @precompiled.encode(Encoding.find(@options[:encoding]))
end
|
#render(scope = Object.new, locals = {}, &block) ⇒ String 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 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.
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/haml/engine.rb', line 163
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
|
#render_proc(scope = Object.new, *local_names) ⇒ Proc
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.
216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/haml/engine.rb', line 216
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
Returns Whether or not the format is XHTML.
34 35 36 |
# File 'lib/haml/engine.rb', line 34
def xhtml?
not html?
end
|