diff --git a/lib/pretty_hamlit/compiler.rb b/lib/pretty_hamlit/compiler.rb index c8b47264..464c2400 100644 --- a/lib/pretty_hamlit/compiler.rb +++ b/lib/pretty_hamlit/compiler.rb @@ -1,4 +1,5 @@ require 'hamlit/compiler' +require 'pretty_hamlit/compiler/tag_compiler' require 'pretty_hamlit/filters' require 'pretty_hamlit/whitespace_compiler' @@ -7,6 +8,7 @@ module PrettyHamlit def initialize(options = {}) super @indent_level = 0 + @tag_compiler = TagCompiler.new(options) @filter_compiler = Filters.new(options) @whitespace_compiler = WhitespaceCompiler.new @@ -31,7 +33,7 @@ module PrettyHamlit def compile_tag(node) @indent_level += 1 - super + @tag_compiler.compile(node, @indent_level) { |n| compile_children(n) } ensure @indent_level -= 1 end diff --git a/lib/pretty_hamlit/compiler/tag_compiler.rb b/lib/pretty_hamlit/compiler/tag_compiler.rb new file mode 100644 index 00000000..0327c698 --- /dev/null +++ b/lib/pretty_hamlit/compiler/tag_compiler.rb @@ -0,0 +1,39 @@ +require 'hamlit/compiler/tag_compiler' + +module PrettyHamlit + class Compiler < Hamlit::Compiler + class TagCompiler < Hamlit::Compiler::TagCompiler + def initialize(options = {}) + super + @buffer = options[:buffer] + end + + def compile(node, indent_level, &block) + attrs = compile_attributes(node) + contents = compile_contents(node, indent_level, &block) + [:html, :tag, node.value[:name], attrs, contents] + end + + private + + def compile_contents(node, indent_level, &block) + case + when !node.children.empty? + yield(node) + when node.value[:value].nil? && self_closing?(node) + nil + when node.value[:parse] + [:multi, + [:code, "#{@buffer} << ::PrettyHamlit::DynamicIndentation.inline_or_expand(#{indent_level}) do |#{@buffer}|"], + [:dynamic, node.value[:value]], + [:code, 'end'], + ] + when Haml::Util.contains_interpolation?(node.value[:value]) + [:dynamic, node.value[:value]] + else + [:static, node.value[:value]] + end + end + end + end +end diff --git a/lib/pretty_hamlit/dynamic_indentation.rb b/lib/pretty_hamlit/dynamic_indentation.rb index 900bd01a..7a275d02 100644 --- a/lib/pretty_hamlit/dynamic_indentation.rb +++ b/lib/pretty_hamlit/dynamic_indentation.rb @@ -1,10 +1,32 @@ module PrettyHamlit class DynamicIndentation class << self - def indent_with(indent_level) - indent = "\n" << ' ' * indent_level - text = yield('') - text.gsub("\n", indent) + def indent_with(indent_level, &block) + text = capture(&block) + insert_indent(text, indent_level) + end + + def inline_or_expand(indent_level, &block) + text = capture(&block) + return text unless text.include?("\n") + + indent_space(indent_level) << + insert_indent(text, indent_level) << + indent_space(indent_level - 1) + end + + private + + def indent_space(indent_level) + "\n" << ' ' * [indent_level, 0].max + end + + def insert_indent(text, indent_level) + text.gsub("\n", indent_space(indent_level)) + end + + def capture(&block) + block.call([]).compact.join.rstrip end end end diff --git a/test/engine_test.rb b/test/engine_test.rb index 1378ccca..cb955fd8 100644 --- a/test/engine_test.rb +++ b/test/engine_test.rb @@ -222,7 +222,7 @@ HAML assert_equal("

Hello

", render('%p Hello').chomp) end - def test_one_liner_with_newline_shouldnt_be_one_line; skip # dynamic indentation # script bug + def test_one_liner_with_newline_shouldnt_be_one_line assert_equal("

\n foo\n bar\n

", render('%p= "foo\nbar"').chomp) end