1
0
Fork 0
mirror of https://github.com/haml/haml.git synced 2022-11-09 12:33:31 -05:00

Merged text now possible. To make blocks of multiline text work, push_silent now takes a tag when it is being

used as a one liner, allowing it to close itself so push_text can stop worrying about potential one liner
pending situation.  Same goes for opening non pre-rendered tags which can now close their own content after
determining one liner status.  Extra complexity there pays off in multi line plain text now being easy to dump.
Sequential push_texts are now merged into single multi line calls, next step is merging pre-rendered open
tags and close tags.



git-svn-id: svn://hamptoncatlin.com/haml/trunk@553 7063305b-7217-0410-af8c-cdc13e5119b9
This commit is contained in:
tom 2007-07-13 01:09:10 +00:00
parent c1d5fb52e3
commit ab1dffda9e
3 changed files with 82 additions and 23 deletions

View file

@ -42,7 +42,7 @@ module Haml
# Renders +text+ with the proper tabulation. This also deals with
# making a possible one-line tag one line or not.
def push_text(text, tabulation)
def push_text(text, tab_change = 0)
if @one_liner_pending && Buffer.one_liner?(text)
@buffer << text
else
@ -50,13 +50,18 @@ module Haml
@buffer << "\n"
@one_liner_pending = false
end
@buffer << "#{tabs(tabulation)}#{text}\n"
if(@tabulation > 0)
text.gsub!(/^/m, ' ')
end
@buffer << "#{text}"
end
@real_tabs += tab_change
end
# Properly formats the output of a script that was run in the
# instance_eval.
def push_script(result, tabulation, flattened)
def push_script(result, tabulation, flattened, close_tag = nil)
if flattened
result = Haml::Helpers.find_and_preserve(result)
end
@ -67,8 +72,25 @@ module Haml
result = result[0...-1]
end
result = result.gsub("\n", "\n#{tabs(tabulation)}")
push_text result, tabulation
if @one_liner_pending && Buffer.one_liner?(result)
@buffer << result
@buffer << "</#{close_tag}>\n"
@one_liner_pending = false
@real_tabs -= 1
else
if @one_liner_pending
@buffer << "\n"
tabulation += 1
end
result = result.gsub("\n", "\n#{tabs(tabulation)}")
@buffer << "#{tabs(tabulation)}#{result}\n"
if @one_liner_pending
@one_liner_pending = false
@buffer << "#{tabs(tabulation-1)}</#{close_tag}>\n"
end
end
end
nil
end
@ -81,7 +103,7 @@ module Haml
# Takes the various information about the opening tag for an
# element, formats it, and adds it to the buffer.
def open_tag(name, tabulation, atomic, try_one_line, class_id, obj_ref, attributes_hash)
def open_tag(name, tabulation, atomic, try_one_line, class_id, obj_ref, content, attributes_hash)
attributes = class_id
if attributes_hash
attributes_hash.keys.each { |key| attributes_hash[key.to_s] = attributes_hash.delete(key) }
@ -99,7 +121,16 @@ module Haml
str = ">\n"
end
@buffer << "#{tabs(tabulation)}<#{name}#{build_attributes(attributes)}#{str}"
@real_tabs += 1
if content
if Buffer.one_liner?(content)
@buffer << "#{content}</#{name}>\n"
else
@buffer << "\n#{tabs(@real_tabs+1)}#{content}\n#{tabs(@real_tabs)}</#{name}>\n"
end
@one_liner_pending = false
else
@real_tabs += 1
end
end
def self.merge_attrs(to, from)
@ -117,11 +148,12 @@ module Haml
# Creates a closing tag with the given name.
def close_tag(name, tabulation)
@real_tabs = tabulation
if @one_liner_pending
@buffer << "</#{name}>\n"
@one_liner_pending = false
else
push_text("</#{name}>", tabulation)
push_text("#{' ' * tabulation}</#{name}>\n")
end
end
@ -159,7 +191,6 @@ module Haml
@@tab_cache = {}
# Gets <tt>count</tt> tabs. Mostly for internal use.
def tabs(count)
@real_tabs = count
tabs = count + @tabulation
' ' * tabs
@@tab_cache[tabs] ||= ' ' * tabs

View file

@ -467,6 +467,8 @@ END
# Evaluates <tt>text</tt> in the context of <tt>@scope_object</tt>, but
# does not output the result.
def push_silent(text, add_index = false, can_suppress = false)
flush_merged_text
unless (can_suppress && options[:suppress_eval])
if add_index
@precompiled << "@haml_lineno = #{@index}\n#{text}\n"
@ -479,9 +481,22 @@ END
# Adds <tt>text</tt> to <tt>@buffer</tt> with appropriate tabulation
# without parsing it.
def push_text(text)
@precompiled << "_hamlout.push_text(#{text.dump}, #{@output_tabs})\n"
def push_text(text, tab_change = 0)
@merged_text ||= ''
@merged_text << "#{' ' * @output_tabs}#{text}\n"
@tab_change ||= 0
@tab_change += tab_change
end
def flush_merged_text
if @merged_text && !@merged_text.empty?
args = @merged_text.dump
args += ", #{@tab_change}" if @tab_change != 0
@precompiled << "_hamlout.push_text(#{args})\n"
@merged_text = nil
@tab_change = 0
end
end
# Renders a block of text as plain text.
# Also checks for an illegally opened block.
@ -504,10 +519,12 @@ END
#
# If <tt>flattened</tt> is true, Haml::Helpers#find_and_flatten is run on
# the result before it is added to <tt>@buffer</tt>
def push_script(text, flattened)
def push_script(text, flattened, close_tag = nil)
flush_merged_text
unless options[:suppress_eval]
push_silent("haml_temp = #{text}", true)
out = "haml_temp = _hamlout.push_script(haml_temp, #{@output_tabs}, #{flattened})\n"
out = "haml_temp = _hamlout.push_script(haml_temp, #{@output_tabs}, #{flattened}, #{close_tag.inspect})\n"
if @block_opened
push_and_tabulate([:loud, out])
else
@ -519,6 +536,8 @@ END
# Causes <tt>text</tt> to be evaluated, and Haml::Helpers#find_and_flatten
# to be run on it afterwards.
def push_flat_script(text)
flush_merged_text
if text.empty?
raise SyntaxError.new("Tag has no content.")
else
@ -555,6 +574,8 @@ END
# Puts a line in <tt>@precompiled</tt> that will add the closing tag of
# the most recently opened tag.
def close_tag(tag)
flush_merged_text
@output_tabs -= 1
@template_tabs -= 1
@precompiled << "_hamlout.close_tag(#{tag.dump}, #{@output_tabs})\n"
@ -571,7 +592,7 @@ END
@output_tabs -= 1
@template_tabs -= 1
close_tag = has_conditional ? "<![endif]-->" : "-->"
push_text(close_tag)
push_text(close_tag, -1)
end
# Closes a loud Ruby block.
@ -699,6 +720,8 @@ END
# Parses a line that will render as an XHTML tag, and adds the code that will
# render that tag to <tt>@precompiled</tt>.
def render_tag(line)
flush_merged_text
matched = false
line.scan(TAG_REGEX) do |tag_name, attributes, attributes_hash, object_ref, action, value|
matched = true
@ -718,6 +741,11 @@ END
flattened = (action == '~')
value_exists = !value.empty?
if value_exists && parse && @options[:suppress_eval]
parse = false
value = ''
end
literal_attributes = parse_literal_hash(attributes_hash)
attributes_hash = "{nil}" if attributes_hash.nil? || literal_attributes || @options[:suppress_eval]
object_ref = "nil" if object_ref.nil? || @options[:suppress_eval]
@ -761,20 +789,20 @@ END
push_silent "_hamlout.open_prerendered_tag(#{open_tag.dump}, #{@output_tabs}, #{parse.inspect}, #{tag_closed.inspect})"
return if tag_closed
else
push_silent "_hamlout.open_tag(#{tag_name.inspect}, #{@output_tabs}, #{atomic.inspect}, #{value_exists.inspect}, #{attributes.inspect}, #{object_ref}, #{attributes_hash[1...-1]})", true
content = !value_exists || parse ? 'nil' : value.dump
push_silent "_hamlout.open_tag(#{tag_name.inspect}, #{@output_tabs}, #{atomic.inspect}, #{value_exists.inspect}, #{attributes.inspect}, #{object_ref}, #{content}, #{attributes_hash[1...-1]})", true
end
unless atomic
push_and_tabulate([:element, tag_name])
@output_tabs += 1
unless value_exists
push_and_tabulate([:element, tag_name])
@output_tabs += 1
end
if value_exists
if parse
push_script(value, flattened)
else
push_text(value)
push_script(value, flattened, tag_name)
end
close
elsif flattened
raise SyntaxError.new("Tag has no content.")
end
@ -807,7 +835,7 @@ END
close_tag = conditional ? "<![endif]-->" : "-->"
push_text("#{text_out}#{content} #{close_tag}")
else
push_text(text_out)
push_text(text_out, 1)
@output_tabs += 1
push_and_tabulate([:comment, !conditional.nil?])
if !content.empty?

View file

@ -101,7 +101,7 @@ class EngineTest < Test::Unit::TestCase
# Make sure the method called will return junk unless recompiled
method_name = Haml::Engine.send(:class_variable_get, '@@method_names')[template]
Haml::Engine::CompiledTemplates.module_eval "def #{method_name}(stuff); @haml_stack[-1].push_text 'NOT RECOMPILED', 0; end"
Haml::Engine::CompiledTemplates.module_eval "def #{method_name}(stuff); @haml_stack[-1].push_text(\"NOT RECOMPILED\n\"); end"
assert_equal("NOT RECOMPILED\n", render(template, :locals => { :text => "first time" }))
assert_equal("<p>first time</p>\n", render(template, :locals => { :text => "first time", :foo => 'bar' }))