require 'haml/helpers'
require 'haml/buffer'
require 'haml/precompiler'
require 'haml/filters'
require 'haml/error'
module Haml
# 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
class Engine
include Precompiler
# Allow reading and writing of the options hash
attr :options, true
# This string contains the source code that is evaluated
# to produce the Haml document.
attr :precompiled, true
# True if the format is XHTML
def xhtml?
not html?
end
# True if the format is any flavor of HTML
def html?
html4? or html5?
end
# True if the format is HTML4
def html4?
@options[:format] == :html4
end
# True if the format is HTML5
def html5?
@options[:format] == :html5
end
# Creates a new instace of Haml::Engine that will compile the given
# template string when render is called.
# See README.rdoc for available options.
#
#--
# When adding options, remember to add information about them
# to README.rdoc!
#++
#
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],
:filters => {
'sass' => Haml::Filters::Sass,
'plain' => Haml::Filters::Plain,
'javascript' => Haml::Filters::Javascript,
'preserve' => Haml::Filters::Preserve,
'redcloth' => Haml::Filters::RedCloth,
'textile' => Haml::Filters::Textile,
'markdown' => Haml::Filters::Markdown },
:filename => '(haml)',
:line => 1,
:ugly => false,
:format => :xhtml,
:escape_html => false
}
@options[:filters].merge! options.delete(:filters) if options[:filters]
@options.merge! options
unless [:xhtml, :html4, :html5].include?(@options[:format])
raise Haml::Error, "Invalid format #{@options[:format].inspect}"
end
unless @options[:suppress_eval]
@options[:filters].merge!({
'erb' => Haml::Filters::ERB,
'ruby' => Haml::Filters::Ruby
})
end
if @options[:locals]
warn < FOOBAR Hello, world! Hello! \n Today's date is\n
Hello!
" # # # 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"). 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 private 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 # Returns a hash of options that Haml::Buffer cares about. # This should remain loadable from #inspect. def options_for_buffer { :autoclose => @options[:autoclose], :preserve => @options[:preserve], :attr_wrapper => @options[:attr_wrapper], :ugly => @options[:ugly], :format => @options[:format] } end end end