lib/middleman-core/renderers/haml.rb
# Require gem require 'haml' # Require padrino-helpers now so that we get a chance to replace their renderer with ours in Tilt. require 'padrino-helpers' module SafeTemplate def render(*) super.html_safe end end class Tilt::HamlTemplate include SafeTemplate end module Middleman module Renderers # Haml precompiles filters before the scope is even available, # thus making it impossible to pass our Middleman instance # in. So we have to resort to heavy hackery :( class HamlTemplate < ::Tilt::HamlTemplate def initialize(*args, &block) super @context = @options[:context] end def prepare; end def evaluate(scope, locals, &block) options = {}.merge!(@options).merge!(context: @context || scope) if options.include?(:outvar) options[:buffer] = options.delete(:outvar) options[:save_buffer] = true end if Object.const_defined?('::Haml::Template') # haml 6+ @engine = ::Haml::Template.new(eval_file, line, options) { data } else options[:filename] = eval_file options[:line] = line @engine = ::Haml::Engine.new(data, options) end output = @engine.render(scope, locals, &block) output end end # Haml Renderer class Haml < ::Middleman::Extension def initialize(app, options={}, &block) super if Object.const_defined?('::Haml::Options') # Haml 5 and older ::Haml::Options.defaults[:context] = nil ::Haml::Options.send :attr_accessor, :context else # Haml 6+ ::Haml::Engine.define_options context: nil end if defined?(::Haml::TempleEngine) ::Haml::TempleEngine.define_options context: nil end [::Haml::Filters::Sass, ::Haml::Filters::Scss, ::Haml::Filters::Markdown].each do |f| f.class_exec do if respond_to?(:template_class) # Haml 5 and older def self.render_with_options(text, compiler_options) modified_options = options.dup modified_options[:context] = compiler_options[:context] text = template_class.new(nil, 1, modified_options) { text }.render super(text, compiler_options) end else # Haml 6+ def initialize(options = {}) super @context = options[:context] end def compile_with_tilt(node, name, indent_width: 0) options = { context: @context } source = node.value[:text] result = ::Tilt["t.#{name}"].new(nil, 1, options) { source }.render temple = [:multi, [:static, result.gsub(/^/, ' ' * indent_width)]] source.lines.size.times do temple << [:newline] end temple end end end end ::Tilt.prefer(::Middleman::Renderers::HamlTemplate, :haml) # Add haml helpers to context ::Middleman::TemplateContext.send :include, ::Haml::Helpers end def add_exposed_to_context(context) super context.init_haml_helpers if context.respond_to?(:init_haml_helpers) end end end end