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

Closing patch #34 and converting over to a buffered engine.

git-svn-id: svn://hamptoncatlin.com/haml/trunk@58 7063305b-7217-0410-af8c-cdc13e5119b9
This commit is contained in:
hcatlin 2006-10-02 23:49:53 +00:00
parent f983380373
commit 8d7b7d407c
5 changed files with 113 additions and 56 deletions

View file

@ -17,128 +17,172 @@ module Haml #:nodoc:
options.each { |k,v| eval("@#{k} = v") }
@template = template #String
@result, @to_close_queue = String.new, []
@result, @precompiled, @to_close_queue = String.new, String.new, []
@scope_object = Object.new if @scope_object.nil?
end
def to_html
# Process each line of the template
@template.each_with_index do |line, index|
count, line = count_soft_tabs(line)
surpress_render, line, count = handle_multiline(count, line)
suppress_render, line, count = handle_multiline(count, line)
if !surpress_render && count && line
if !suppress_render && count && line
count, line = process_line(count, line)
end
end
# Make sure an ending multiline gets closed
handle_multiline(0, nil)
# Close all the open tags
@to_close_queue.length.times { close_tag }
# Compile the @precompiled buffer
compile
# Return the result string
@result
end
def process_line(count, line)
if line.strip[0, 3] == '!!!'
@result << %|<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n|
push_text %|<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">|
else
if count <= @to_close_queue.size && @to_close_queue.size > 0
(@to_close_queue.size - count).times { close_tag }
end
case line[0..0]
when '.', '#'
render_div(line)
when '%'
render_tag(line)
when '/'
render_comment(line)
when '='
add template_eval(line[1, line.length]).to_s
when '~'
add find_and_flatten(template_eval(line[1, line.length])).to_s
else
add line.strip
if line.length > 0
case line[0].chr
when '.', '#'
render_div(line)
when '%'
render_tag(line)
when '/'
render_comment(line)
when '='
push_script(line[1, line.length])
when '~'
push_script(line[1, line.length], true)
else
push_text line.strip
end
end
end
return count, line
end
def handle_multiline(count, line)
# Multilines are denoting by ending with a `|` (124)
if (line[-1] == MULTILINE_CHAR_VALUE) && @multiline_buffer
if line && (line[-1] == MULTILINE_CHAR_VALUE) && @multiline_buffer
# A multiline string is active, and is being continued
@multiline_buffer += line[0...-1]
supress_render = true
elsif (line[-1] == MULTILINE_CHAR_VALUE) && (MULTILINE_STARTERS.include? line[0])
suppress_render = true
elsif line && (line[-1] == MULTILINE_CHAR_VALUE) && (MULTILINE_STARTERS.include? line[0])
# A multiline string has just been activated, start adding the lines
@multiline_buffer = line[0...-1]
@multiline_count = count
supress_render = true
suppress_render = true
elsif @multiline_buffer
# A multiline string has just ended, make line into the result
process_line(@multiline_count, @multiline_buffer)
@multiline_buffer = nil
supress_render = false
suppress_render = false
end
return supress_render, line, count
return suppress_render, line, count
end
def add(line)
return if line.nil?
line.to_s.each_line do |me|
@result << tabs(@to_close_queue.size) << me.chomp << "\n"
def compile
# Set the local variables pointing to the buffer
result = @result
@scope_object.instance_eval do
@haml_stack =|| Array.new
@haml_stack.push(result)
self.class.instance_eval { include Haml::Helpers }
end
# Evaluate the buffer in the context of the scope object
# This automatically dumps the result into @result
@scope_object.instance_eval @precompiled
# Get rid of the current buffer
@scope_object.instance_eval do
@haml_stack.pop
end
end
def push_visible(text)
@precompiled << "@haml_stack[-1] << #{tabs(@to_close_queue.size).dump} << #{text}\n"
end
def push_silent(text)
@precompiled << "#{text}\n"
end
def push_text(text)
push_visible("#{text.dump} << \"\\n\"")
end
def push_script(text, flattened = false)
unless @suppress_eval
push_silent("haml_temp = #{text}")
if flattened
push_silent("haml_temp = find_and_flatten(haml_temp)")
end
push_visible("#{wrap_script("haml_temp", @to_close_queue.size)} << \"\\n\"")
end
end
def build_attributes(attributes = {})
result = attributes.collect { |a,v|
result = attributes.collect do |a,v|
unless v.nil?
first_quote_type = v.to_s.scan(/['"]/).first
quote_type = (first_quote_type == "'") ? '"' : "'"
"#{a.to_s}=#{quote_type}#{v.to_s}#{quote_type}"
end
}
end
result = result.compact.join(' ')
(attributes.empty? ? String.new : String.new(' ')) + result
end
def open_tag(name, attributes = {})
add "<#{name.to_s}#{build_attributes(attributes)}>"
push_text "<#{name.to_s}#{build_attributes(attributes)}>"
@to_close_queue.push name
end
def close_tag
add "</#{@to_close_queue.pop}>"
push_text "</#{@to_close_queue.pop}>"
end
def one_line_tag(name, value, attributes = {})
add "<#{name.to_s}#{build_attributes(attributes)}>#{value}</#{name.to_s}>"
push_text "<#{name.to_s}#{build_attributes(attributes)}>#{value}</#{name.to_s}>"
end
def one_liner?(value)
value.length <= ONE_LINER_LENGTH && value.scan(/\n/).empty?
end
def print_tag(name, value, attributes = {})
def push_tag(name, value, attributes = {}, parse = false, flattened = false)
unless value.empty?
if one_liner? value
if !parse && one_liner?(value)
one_line_tag(name, value, attributes)
else
open_tag(name, attributes)
add value
if parse
push_script(value, flattened)
else
push_text(value)
end
close_tag
end
else
open_tag(name, attributes)
add value
end
end
# Creates single line tags, i.e. <tt><hello /></tt>
def atomic_tag(name, attributes = {})
add "<#{name.to_s}#{build_attributes(attributes)} />"
push_text "<#{name.to_s}#{build_attributes(attributes)} />"
end
def parse_class_and_id(list)
@ -174,11 +218,10 @@ module Haml #:nodoc:
when '/'
atomic_tag(tag_name, attributes)
when '=', '~'
value = template_eval(value)
value = find_and_flatten(value) if action == '~'
print_tag(tag_name, value.to_s, attributes)
flattened = (action == '~')
push_tag(tag_name, value.to_s, attributes, true, flattened) if value
else
print_tag(tag_name, value.to_s.strip, attributes)
push_tag(tag_name, value.to_s.strip, attributes)
end
end
end
@ -188,7 +231,7 @@ module Haml #:nodoc:
end
def render_comment(line)
add "<!-- #{line[1..line.length].strip} -->"
push_text "<!-- #{line[1..line.length].strip} -->"
end
def template_eval(args)

View file

@ -21,6 +21,10 @@ module Haml
line.index(/[^ ]/) ? [line.index(/[^ ]/)/2, line.strip] : []
end
def wrap_script(script, count)
"(#{script}).to_s.chomp.gsub(\"\\n\", \"\\n#{tabs(count)}\")"
end
# List_for is a really nifty little helper that helps
# cleanup your code. Basically, give it an array of
# objects, and then pass in a block that tells how

View file

@ -1,5 +1,11 @@
<div class='article' id='article_1'>
<h1>Hello</h1>
<div>World</div>
<h1>
Hello
</h1>
<div>
World
</div>
</div>
<div class='article full' id='article_1'>
boo
</div>
<div class='article full' id='article_1'>boo</div>

View file

@ -12,14 +12,18 @@
The question is if this would translate! Ahah!
20
</div>
<div id='body'> Quotes should be loved! Just like people!</div>
<div id='body'>
Quotes should be loved! Just like people!
</div>
Wow.|
<p>
Holy cow multiline tags! A pipe (|) even!
PipesIgnored|PipesIgnored|PipesIgnored|
1|2|3
</p>
<div class='of_divs_with_underscore' id='combo'>with this text</div>
<div class='of_divs_with_underscore' id='combo'>
with this text
</div>
<div class='footer'>
<strong class='shout'>
This is a really long ruby quote. It should be loved and wrapped because its more than 50 characters. This value may change in the future and this test may look stupid.

View file

@ -5,7 +5,7 @@
<meta content='text/html; charset=utf-8' http-equiv='Content-Type' />
</head>
<body>
<!-- You're In my house now! -->
<!-- <%= "You're In my house now!" %> -->
<div class='header'>
Yes, ladies and gentileman. He is just that egotistical.
Fantastic! This should be multi-line output