mirror of
https://github.com/haml/haml.git
synced 2022-11-09 12:33:31 -05:00
Move compiler into its own class
This commit is contained in:
parent
cf6a83798a
commit
eb9a366730
6 changed files with 64 additions and 56 deletions
|
@ -1,10 +1,51 @@
|
|||
require 'cgi'
|
||||
|
||||
module Haml
|
||||
module Compiler
|
||||
class Compiler
|
||||
include Haml::Util
|
||||
|
||||
private
|
||||
attr_accessor :options
|
||||
|
||||
def initialize(options)
|
||||
@options = options
|
||||
@output_tabs = 0
|
||||
@to_merge = []
|
||||
@precompiled = ''
|
||||
end
|
||||
|
||||
def compile(node)
|
||||
parent = instance_variable_defined?('@node') ? @node : nil
|
||||
@node = node
|
||||
if node.children.empty?
|
||||
send(:"compile_#{node.type}")
|
||||
else
|
||||
send(:"compile_#{node.type}") {node.children.each {|c| compile c}}
|
||||
end
|
||||
ensure
|
||||
@node = parent
|
||||
end
|
||||
|
||||
if RUBY_VERSION < "1.9"
|
||||
# The source code that is evaluated to produce the Haml document.
|
||||
#
|
||||
# In Ruby 1.9, this is automatically converted to the correct encoding
|
||||
# (see {file:REFERENCE.md#encodings the `:encoding` option}).
|
||||
#
|
||||
# @return [String]
|
||||
def precompiled
|
||||
@precompiled
|
||||
end
|
||||
else
|
||||
def precompiled
|
||||
encoding = Encoding.find(@options[:encoding])
|
||||
return @precompiled.force_encoding(encoding) if encoding == Encoding::BINARY
|
||||
return @precompiled.encode(encoding)
|
||||
end
|
||||
end
|
||||
|
||||
def precompiled_with_return_value
|
||||
precompiled + ";" + precompiled_method_return_value
|
||||
end
|
||||
|
||||
# Returns the precompiled string with the preamble and postamble
|
||||
def precompiled_with_ambles(local_names)
|
||||
|
@ -23,6 +64,8 @@ END
|
|||
preamble + locals_code(local_names) + precompiled + postamble
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# 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
|
||||
|
@ -260,7 +303,7 @@ END
|
|||
# does not output the result.
|
||||
def push_silent(text, can_suppress = false)
|
||||
flush_merged_text
|
||||
return if can_suppress && options[:suppress_eval]
|
||||
return if can_suppress && @options.suppress_eval?
|
||||
@precompiled << "#{resolve_newlines}#{text}\n"
|
||||
@output_line += text.count("\n") + 1
|
||||
end
|
||||
|
@ -321,7 +364,7 @@ END
|
|||
# If `opts[:preserve_script]` is true, Haml::Helpers#find_and_flatten is run on
|
||||
# the result before it is added to `@buffer`
|
||||
def push_script(text, opts = {})
|
||||
return if options[:suppress_eval]
|
||||
return if @options.suppress_eval?
|
||||
|
||||
args = %w[preserve_script in_tag preserve_tag escape_html nuke_inner_whitespace]
|
||||
args.map! {|name| opts[name.to_sym]}
|
||||
|
@ -479,17 +522,5 @@ END
|
|||
raise SyntaxError.new("[HAML BUG] Undefined entry in Haml::Compiler@to_merge.")
|
||||
end
|
||||
end
|
||||
|
||||
def compile(node)
|
||||
parent = instance_variable_defined?('@node') ? @node : nil
|
||||
@node = node
|
||||
if node.children.empty?
|
||||
send(:"compile_#{node.type}")
|
||||
else
|
||||
send(:"compile_#{node.type}") {node.children.each {|c| compile c}}
|
||||
end
|
||||
ensure
|
||||
@node = parent
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -17,7 +17,7 @@ module Haml
|
|||
# output = haml_engine.render
|
||||
# puts output
|
||||
class Engine
|
||||
include Compiler
|
||||
include Haml::Util
|
||||
|
||||
# The Haml::Options instance.
|
||||
# See {file:REFERENCE.md#options the Haml options documentation}.
|
||||
|
@ -32,23 +32,8 @@ module Haml
|
|||
# @return [String]
|
||||
attr_accessor :indentation
|
||||
|
||||
if RUBY_VERSION < "1.9"
|
||||
# The source code that is evaluated to produce the Haml document.
|
||||
#
|
||||
# In Ruby 1.9, this is automatically converted to the correct encoding
|
||||
# (see {file:REFERENCE.md#encodings the `:encoding` option}).
|
||||
#
|
||||
# @return [String]
|
||||
def precompiled
|
||||
@precompiled
|
||||
end
|
||||
else
|
||||
def precompiled
|
||||
encoding = Encoding.find(@options[:encoding])
|
||||
return @precompiled.force_encoding(encoding) if encoding == Encoding::BINARY
|
||||
return @precompiled.encode(encoding)
|
||||
end
|
||||
end
|
||||
attr_accessor :compiler
|
||||
attr_accessor :parser
|
||||
|
||||
|
||||
# Precompiles the Haml template.
|
||||
|
@ -58,7 +43,6 @@ module Haml
|
|||
# see {file:REFERENCE.md#options the Haml options documentation}
|
||||
# @raise [Haml::Error] if there's a Haml syntax error in the template
|
||||
def initialize(template, options = {})
|
||||
@index = nil # explicitily initialize to avoid warnings
|
||||
@options = Options.new(options)
|
||||
|
||||
@template = check_haml_encoding(template) do |msg, line|
|
||||
|
@ -67,20 +51,10 @@ module Haml
|
|||
|
||||
initialize_encoding options[:encoding]
|
||||
|
||||
@index = 0
|
||||
|
||||
@parser = Parser.new(@template, @options)
|
||||
@compiler = Compiler.new(@options)
|
||||
|
||||
@output_tabs = 0
|
||||
@to_merge = []
|
||||
@precompiled = ''
|
||||
|
||||
compile(@parser.parse)
|
||||
rescue Haml::Error => e
|
||||
if @index || e.line
|
||||
e.backtrace.unshift "#{@options[:filename]}:#{(e.line ? e.line + 1 : @index) + @options[:line] - 1}"
|
||||
end
|
||||
raise
|
||||
@compiler.compile(@parser.parse)
|
||||
end
|
||||
|
||||
# Processes the template and returns the result as a string.
|
||||
|
@ -143,8 +117,7 @@ module Haml
|
|||
@haml_buffer = buffer
|
||||
end
|
||||
|
||||
eval(precompiled + ";" + precompiled_method_return_value,
|
||||
scope, @options[:filename], @options[:line])
|
||||
eval(@compiler.precompiled_with_return_value, scope, @options[:filename], @options[:line])
|
||||
ensure
|
||||
# Get rid of the current buffer
|
||||
scope_object.instance_eval do
|
||||
|
@ -186,7 +159,7 @@ module Haml
|
|||
end
|
||||
|
||||
eval("Proc.new { |*_haml_locals| _haml_locals = _haml_locals[0] || {};" +
|
||||
precompiled_with_ambles(local_names) + "}\n", scope, @options[:filename], @options[:line])
|
||||
compiler.precompiled_with_ambles(local_names) + "}\n", scope, @options[:filename], @options[:line])
|
||||
end
|
||||
|
||||
# Defines a method on `object` with the given name
|
||||
|
@ -230,7 +203,7 @@ module 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",
|
||||
object.send(method, "def #{name}(_haml_locals = {}); #{compiler.precompiled_with_ambles(local_names)}; end",
|
||||
@options[:filename], @options[:line])
|
||||
end
|
||||
|
||||
|
|
|
@ -80,6 +80,7 @@ module Haml
|
|||
@template = (template.rstrip).split(/\r\n|\r|\n/) + [:eod, :eod]
|
||||
@options = options
|
||||
@flat = false
|
||||
@index = 0
|
||||
@template_index = 0
|
||||
@template_tabs = 0
|
||||
end
|
||||
|
@ -120,6 +121,9 @@ module Haml
|
|||
# Close all the open tags
|
||||
close until @parent.type == :root
|
||||
@root
|
||||
rescue Haml::Error => e
|
||||
e.backtrace.unshift "#{@options[:filename]}:#{(e.line ? e.line + 1 : @index) + @options[:line] - 1}"
|
||||
raise
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ require 'haml/helpers/action_view_extensions'
|
|||
require 'haml/helpers/xss_mods'
|
||||
|
||||
module Haml
|
||||
module Compiler
|
||||
class Compiler
|
||||
def precompiled_method_return_value_with_haml_xss
|
||||
"::Haml::Util.html_safe(#{precompiled_method_return_value_without_haml_xss})"
|
||||
end
|
||||
|
|
|
@ -18,7 +18,7 @@ module Haml
|
|||
options = Haml::Template.options.dup
|
||||
options[:mime_type] = template.mime_type if template.respond_to? :mime_type
|
||||
options[:filename] = template.identifier
|
||||
Haml::Engine.new(template.source, options).send(:precompiled_with_ambles, [])
|
||||
Haml::Engine.new(template.source, options).compiler.precompiled_with_ambles([])
|
||||
end
|
||||
|
||||
# In Rails 3.1+, #call takes the place of #compile
|
||||
|
|
|
@ -41,9 +41,9 @@ class FiltersTest < MiniTest::Unit::TestCase
|
|||
|
||||
test "should pass options to Tilt filters that precompile" do
|
||||
haml = ":erb\n <%= 'foo' %>"
|
||||
refute_match('TEST_VAR', Haml::Engine.new(haml).precompiled)
|
||||
refute_match('TEST_VAR', Haml::Engine.new(haml).compiler.precompiled)
|
||||
Haml::Filters::Erb.options = {:outvar => 'TEST_VAR'}
|
||||
assert_match('TEST_VAR', Haml::Engine.new(haml).precompiled)
|
||||
assert_match('TEST_VAR', Haml::Engine.new(haml).compiler.precompiled)
|
||||
end
|
||||
|
||||
test "should pass options to Tilt filters that don't precompile" do
|
||||
|
|
Loading…
Reference in a new issue