lib/haml/temple_engine.rb
# frozen_string_literal: true require 'temple' require 'haml/escapable' require 'haml/generator' module Haml class TempleEngine < Temple::Engine define_options( attr_wrapper: "'", autoclose: %w(area base basefont br col command embed frame hr img input isindex keygen link menuitem meta param source track wbr), encoding: nil, escape_attrs: true, escape_html: false, escape_filter_interpolations: nil, filename: '(haml)', format: :html5, hyphenate_data_attrs: true, line: 1, mime_type: 'text/html', preserve: %w(textarea pre code), remove_whitespace: false, suppress_eval: false, cdata: false, parser_class: ::Haml::Parser, compiler_class: ::Haml::Compiler, trace: false, filters: {}, ) use :Parser, -> { options[:parser_class] } use :Compiler, -> { options[:compiler_class] } use Escapable filter :ControlFlow filter :MultiFlattener filter :StaticMerger use Generator def compile(template) initialize_encoding(template, options[:encoding]) @precompiled = call(template) end # The source code that is evaluated to produce the Haml document. # # This is automatically converted to the correct encoding # (see {file:REFERENCE.md#encodings the `:encoding` option}). # # @return [String] def precompiled encoding = Encoding.find(@encoding || '') return @precompiled.dup.force_encoding(encoding) if encoding == Encoding::ASCII_8BIT return @precompiled.encode(encoding) end def precompiled_with_return_value "#{precompiled};#{precompiled_method_return_value}".dup end # The source code that is evaluated to produce the Haml document. # # This is automatically converted to the correct encoding # (see {file:REFERENCE.md#encodings the `:encoding` option}). # # @return [String] def precompiled_with_ambles(local_names, after_preamble: '') preamble = <<END.tr("\n", ';') begin extend Haml::Helpers _hamlout = @haml_buffer = Haml::Buffer.new(haml_buffer, #{Options.new(options).for_buffer.inspect}) _erbout = _hamlout.buffer #{after_preamble} END postamble = <<END.tr("\n", ';') #{precompiled_method_return_value} ensure @haml_buffer = @haml_buffer.upper if @haml_buffer end END "#{preamble}#{locals_code(local_names)}#{precompiled}#{postamble}".dup end private def initialize_encoding(template, given_value) if given_value @encoding = given_value else @encoding = Encoding.default_internal || template.encoding end end # Returns the string used as the return value of the precompiled method. # This method exists so it can be monkeypatched to return modified values. def precompiled_method_return_value "_erbout" end def locals_code(names) names = names.keys if Hash === names names.map do |name| # Can't use || because someone might explicitly pass in false with a symbol sym_local = "_haml_locals[#{inspect_obj(name.to_sym)}]" str_local = "_haml_locals[#{inspect_obj(name.to_s)}]" "#{name} = #{sym_local}.nil? ? #{str_local} : #{sym_local};" end.join end def inspect_obj(obj) case obj when String %Q!"#{obj.gsub(/[\x00-\x7F]+/) {|s| s.inspect[1...-1]}}"! when Symbol ":#{inspect_obj(obj.to_s)}" else obj.inspect end end end end