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:
parent
f983380373
commit
8d7b7d407c
5 changed files with 113 additions and 56 deletions
|
@ -17,36 +17,43 @@ 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]
|
||||
if line.length > 0
|
||||
case line[0].chr
|
||||
when '.', '#'
|
||||
render_div(line)
|
||||
when '%'
|
||||
|
@ -54,91 +61,128 @@ module Haml #:nodoc:
|
|||
when '/'
|
||||
render_comment(line)
|
||||
when '='
|
||||
add template_eval(line[1, line.length]).to_s
|
||||
push_script(line[1, line.length])
|
||||
when '~'
|
||||
add find_and_flatten(template_eval(line[1, line.length])).to_s
|
||||
push_script(line[1, line.length], true)
|
||||
else
|
||||
add line.strip
|
||||
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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue