public
Description: HTML Abstraction Markup Language - A Markup Haiku
Homepage: http://haml.hamptoncatlin.com
Clone URL: git://github.com/nex3/haml.git
haml / lib / haml / buffer.rb
89a10b9d » hcatlin 2006-10-14 Creating the next set of br... 1 module Haml
2 # This class is used only internally. It holds the buffer of XHTML that
3 # is eventually output by Haml::Engine's to_html method. It's called
4 # from within the precompiled code, and helps reduce the amount of
5 # processing done within instance_eval'd code.
6 class Buffer
7 include Haml::Helpers
00ef3f99 » nex3 2006-11-03 Better facilities for white... 8
89a10b9d » hcatlin 2006-10-14 Creating the next set of br... 9 # The string that holds the compiled XHTML. This is aliased as
10 # _erbout for compatibility with ERB-specific code.
11 attr_accessor :buffer
00ef3f99 » nex3 2006-11-03 Better facilities for white... 12
b814ea29 » nex3 2007-11-21 Various quote-rendering fix... 13 # The options hash passed in from Haml::Engine.
14 attr_accessor :options
15
6c0473e3 » nex3 2008-04-24 Replace @haml_stack with a ... 16 # The Buffer for the enclosing Haml document.
17 # This is set for partials and similar sorts of nested templates.
18 # It's nil at the top level (see #toplevel?).
19 attr_accessor :upper
20
f48294c4 » nex3 2008-04-24 Keep track of non-Haml-ness... 21 # See #active?
22 attr_writer :active
23
ae3c44f5 » nex3 2008-02-29 Allow rendering of <input c... 24 # True if the format is XHTML
25 def xhtml?
26 not html?
27 end
28
29 # True if the format is any flavor of HTML
30 def html?
31 html4? or html5?
32 end
33
34 # True if the format is HTML4
35 def html4?
36 @options[:format] == :html4
37 end
38
39 # True if the format is HTML5
40 def html5?
41 @options[:format] == :html5
42 end
43
6c0473e3 » nex3 2008-04-24 Replace @haml_stack with a ... 44 # True if this buffer is a top-level template,
45 # as opposed to a nested partial.
46 def toplevel?
47 upper.nil?
48 end
49
f48294c4 » nex3 2008-04-24 Keep track of non-Haml-ness... 50 # True if this buffer is currently being used to render a Haml template.
51 # However, this returns false if a subtemplate is being rendered,
52 # even if it's a subtemplate of this buffer's template.
53 def active?
54 @active
55 end
56
aeade6a6 » nex3 2007-03-15 Added "puts" helper to outp... 57 # Gets the current tabulation of the document.
58 def tabulation
59 @real_tabs + @tabulation
60 end
61
62 # Sets the current tabulation of the document.
63 def tabulation=(val)
64 val = val - @real_tabs
65 @tabulation = val > -1 ? val : 0
66 end
938101b7 » nex3 2006-11-08 This time, I forgot to chec... 67
89a10b9d » hcatlin 2006-10-14 Creating the next set of br... 68 # Creates a new buffer.
6c0473e3 » nex3 2008-04-24 Replace @haml_stack with a ... 69 def initialize(upper = nil, options = {})
f48294c4 » nex3 2008-04-24 Keep track of non-Haml-ness... 70 @active = true
6c0473e3 » nex3 2008-04-24 Replace @haml_stack with a ... 71 @upper = upper
0c23fc9f » nex3 2007-07-14 Add a default for options[:... 72 @options = {
f7f11e20 » wincent 2008-02-13 Add "ugly" option to Haml::... 73 :attr_wrapper => "'",
ae3c44f5 » nex3 2008-02-29 Allow rendering of <input c... 74 :ugly => false,
75 :format => :xhtml
0c23fc9f » nex3 2007-07-14 Add a default for options[:... 76 }.merge options
89a10b9d » hcatlin 2006-10-14 Creating the next set of br... 77 @buffer = ""
938101b7 » nex3 2006-11-08 This time, I forgot to chec... 78 @tabulation = 0
aeade6a6 » nex3 2007-03-15 Added "puts" helper to outp... 79
80 # The number of tabs that Engine thinks we should have
81 # @real_tabs + @tabulation is the number of tabs actually output
82 @real_tabs = 0
89a10b9d » hcatlin 2006-10-14 Creating the next set of br... 83 end
00ef3f99 » nex3 2006-11-03 Better facilities for white... 84
89a10b9d » hcatlin 2006-10-14 Creating the next set of br... 85 # Renders +text+ with the proper tabulation. This also deals with
86 # making a possible one-line tag one line or not.
5834545b » nex3 2008-05-10 Add an > operator to get ri... 87 def push_text(text, dont_tab_up = false, tab_change = 0)
40da6139 » nex3 2008-02-13 Tweak the :ugly code a little. 88 if @tabulation > 0 && !@options[:ugly]
5834545b » nex3 2008-05-10 Add an > operator to get ri... 89 # Have to push every line in by the extra user set tabulation.
90 # Don't push lines with just whitespace, though,
91 # because that screws up precompiled indentation.
92 text.gsub!(/^(?!\s+$)/m, tabs)
93 text.sub!(tabs, '') if dont_tab_up
89a10b9d » hcatlin 2006-10-14 Creating the next set of br... 94 end
84fdde13 » nex3 2008-04-07 Get rid of trailing whitesp... 95
40da6139 » nex3 2008-02-13 Tweak the :ugly code a little. 96 @buffer << text
ab1dffda » tom 2007-07-12 Merged text now possible. ... 97 @real_tabs += tab_change
5834545b » nex3 2008-05-10 Add an > operator to get ri... 98 @dont_tab_up_next_line = false
89a10b9d » hcatlin 2006-10-14 Creating the next set of br... 99 end
00ef3f99 » nex3 2006-11-03 Better facilities for white... 100
89a10b9d » hcatlin 2006-10-14 Creating the next set of br... 101 # Properly formats the output of a script that was run in the
102 # instance_eval.
204ba031 » nex3 2008-05-10 Add support for the > opera... 103 def push_script(result, preserve_script, in_tag = false, preserve_tag = false,
104 escape_html = false, nuke_inner_whitespace = false)
5eafacd6 » tom 2007-07-13 don't pass tabulation to Bu... 105 tabulation = @real_tabs
a7c9aa9d » nex3 2008-03-02 Automatically preserve Haml... 106
53508642 » nex3 2008-08-03 Make sure %textarea and &= ... 107 result = result.to_s.rstrip
7b5ae8db » nex3 2009-01-08 Fix bug in inner-whitespace... 108 result = result.lstrip if nuke_inner_whitespace
53508642 » nex3 2008-08-03 Make sure %textarea and &= ... 109 result = html_escape(result) if escape_html
110
a7c9aa9d » nex3 2008-03-02 Automatically preserve Haml... 111 if preserve_tag
112 result = Haml::Helpers.preserve(result)
113 elsif preserve_script
535c40c4 » nex3 2008-05-13 Make #find_and_preserve pre... 114 result = Haml::Helpers.find_and_preserve(result, options[:preserve])
89a10b9d » hcatlin 2006-10-14 Creating the next set of br... 115 end
84fdde13 » nex3 2008-04-07 Get rid of trailing whitesp... 116
e5dedfa6 » nex3 2008-05-09 Precompile script tabulatio... 117 has_newline = result.include?("\n")
7c13afde » nex3 2008-06-11 Fix a buffer-tabulation bug... 118 if in_tag && !nuke_inner_whitespace && (@options[:ugly] || !has_newline || preserve_tag)
5834545b » nex3 2008-05-10 Add an > operator to get ri... 119 @buffer << result
120 @real_tabs -= 1
121 return
122 end
123
204ba031 » nex3 2008-05-10 Add support for the > opera... 124 @buffer << "\n" if in_tag && !nuke_inner_whitespace
5834545b » nex3 2008-05-10 Add an > operator to get ri... 125
126 # Precompiled tabulation may be wrong
127 if @tabulation > 0 && !in_tag
128 result = tabs + result
129 end
130
131 if has_newline && !@options[:ugly]
132 result = result.gsub "\n", "\n" + tabs(tabulation)
133
134 # Add tabulation if it wasn't precompiled
204ba031 » nex3 2008-05-10 Add support for the > opera... 135 result = tabs(tabulation) + result if in_tag && !nuke_inner_whitespace
5834545b » nex3 2008-05-10 Add an > operator to get ri... 136 end
204ba031 » nex3 2008-05-10 Add support for the > opera... 137 @buffer << "#{result}"
138 @buffer << "\n" unless nuke_inner_whitespace
5834545b » nex3 2008-05-10 Add an > operator to get ri... 139
204ba031 » nex3 2008-05-10 Add support for the > opera... 140 if in_tag && !nuke_inner_whitespace
5834545b » nex3 2008-05-10 Add an > operator to get ri... 141 # We never get here if @options[:ugly] is true
142 @buffer << tabs(tabulation-1)
9db4d2f3 » nex3 2007-08-16 Fixing "%p= nil" and "%p= f... 143 @real_tabs -= 1
89a10b9d » hcatlin 2006-10-14 Creating the next set of br... 144 end
145 nil
146 end
00ef3f99 » nex3 2006-11-03 Better facilities for white... 147
89a10b9d » hcatlin 2006-10-14 Creating the next set of br... 148 # Takes the various information about the opening tag for an
149 # element, formats it, and adds it to the buffer.
5834545b » nex3 2008-05-10 Add an > operator to get ri... 150 def open_tag(name, self_closing, try_one_line, preserve_tag, escape_html, class_id,
151 nuke_outer_whitespace, nuke_inner_whitespace, obj_ref, content, *attributes_hashes)
5eafacd6 » tom 2007-07-13 don't pass tabulation to Bu... 152 tabulation = @real_tabs
84fdde13 » nex3 2008-04-07 Get rid of trailing whitesp... 153
2f59543e » nex3 2007-05-30 Haml: CSS-style attributes ... 154 attributes = class_id
34500a10 » nex3 2008-10-02 Make sure Haml doesn't dest... 155 attributes_hashes.each do |old|
156 self.class.merge_attrs(attributes, old.inject({}) {|h, (key, val)| h[key.to_s] = val; h})
0141a596 » nex3 2007-06-06 Allow CSS-style attributes,... 157 end
158 self.class.merge_attrs(attributes, parse_object_ref(obj_ref)) if obj_ref
00ef3f99 » nex3 2006-11-03 Better facilities for white... 159
49155711 » cv 2008-10-06 Fixed HTML4 markup for "sel... 160 if self_closing && xhtml?
5834545b » nex3 2008-05-10 Add an > operator to get ri... 161 str = " />" + (nuke_outer_whitespace ? "" : "\n")
89a10b9d » hcatlin 2006-10-14 Creating the next set of br... 162 else
178cabab » nex3 2008-10-06 Round out support for self-... 163 str = ">" + ((if self_closing && html?
164 nuke_outer_whitespace
165 else
166 try_one_line || preserve_tag || nuke_inner_whitespace
167 end) ? "" : "\n")
89a10b9d » hcatlin 2006-10-14 Creating the next set of br... 168 end
40da6139 » nex3 2008-02-13 Tweak the :ugly code a little. 169
402977cc » indirect 2008-03-18 Always escape attribute val... 170 attributes = Precompiler.build_attributes(html?, @options[:attr_wrapper], attributes)
5834545b » nex3 2008-05-10 Add an > operator to get ri... 171 @buffer << "#{nuke_outer_whitespace || @options[:ugly] ? '' : tabs(tabulation)}<#{name}#{attributes}#{str}"
40da6139 » nex3 2008-02-13 Tweak the :ugly code a little. 172
ab1dffda » tom 2007-07-12 Merged text now possible. ... 173 if content
5834545b » nex3 2008-05-10 Add an > operator to get ri... 174 @buffer << "#{content}</#{name}>" << (nuke_outer_whitespace ? "" : "\n")
204ba031 » nex3 2008-05-10 Add support for the > opera... 175 return
ab1dffda » tom 2007-07-12 Merged text now possible. ... 176 end
204ba031 » nex3 2008-05-10 Add support for the > opera... 177
178 @real_tabs += 1 unless self_closing || nuke_inner_whitespace
89a10b9d » hcatlin 2006-10-14 Creating the next set of br... 179 end
00ef3f99 » nex3 2006-11-03 Better facilities for white... 180
0141a596 » nex3 2007-06-06 Allow CSS-style attributes,... 181 def self.merge_attrs(to, from)
182 if to['id'] && from['id']
183 to['id'] << '_' << from.delete('id')
a76b25d1 » nex3 2008-01-10 Fixing a bug where the #.-s... 184 elsif to['id'] || from['id']
185 from['id'] ||= to['id']
0141a596 » nex3 2007-06-06 Allow CSS-style attributes,... 186 end
187
188 if to['class'] && from['class']
189 # Make sure we don't duplicate class names
190 from['class'] = (from['class'].split(' ') | to['class'].split(' ')).join(' ')
a76b25d1 » nex3 2008-01-10 Fixing a bug where the #.-s... 191 elsif to['class'] || from['class']
192 from['class'] ||= to['class']
0141a596 » nex3 2007-06-06 Allow CSS-style attributes,... 193 end
194
195 to.merge!(from)
196 end
197
a241cd4e » nex3 2008-04-24 Get rid of the 50-char one-... Comment 198 private
199
aeade6a6 » nex3 2007-03-15 Added "puts" helper to outp... 200 # Some of these methods are exposed as public class methods
201 # so they can be re-used in helpers.
202
8509286a » nex3 2007-05-08 Caching tabs in Haml::Buffe... 203 @@tab_cache = {}
89a10b9d » hcatlin 2006-10-14 Creating the next set of br... 204 # Gets <tt>count</tt> tabs. Mostly for internal use.
e5dedfa6 » nex3 2008-05-09 Precompile script tabulatio... 205 def tabs(count = 0)
6f610190 » nex3 2008-06-06 Make sure Haml::Buffer neve... 206 tabs = [count + @tabulation, 0].max
8509286a » nex3 2007-05-08 Caching tabs in Haml::Buffe... 207 @@tab_cache[tabs] ||= ' ' * tabs
89a10b9d » hcatlin 2006-10-14 Creating the next set of br... 208 end
00ef3f99 » nex3 2006-11-03 Better facilities for white... 209
89a10b9d » hcatlin 2006-10-14 Creating the next set of br... 210 # Takes an array of objects and uses the class and id of the first
211 # one to create an attributes hash.
15332d55 » stefanoc 2008-04-09 Modified Haml::Buffer#parse... 212 # The second object, if present, is used as a prefix,
213 # just like you can do with dom_id() and dom_class() in Rails
0141a596 » nex3 2007-06-06 Allow CSS-style attributes,... 214 def parse_object_ref(ref)
15332d55 » stefanoc 2008-04-09 Modified Haml::Buffer#parse... 215 prefix = ref[1]
89a10b9d » hcatlin 2006-10-14 Creating the next set of br... 216 ref = ref[0]
4158db05 » hcatlin 2006-11-05 Fixing the problem where... 217 # Let's make sure the value isn't nil. If it is, return the default Hash.
218 return {} if ref.nil?
18c7df96 » nex3 2007-03-30 Allow object_ref to be used... 219 class_name = underscore(ref.class)
d30629a9 » nex3 2007-04-16 Intuitive handling for clas... 220 id = "#{class_name}_#{ref.id || 'new'}"
15332d55 » stefanoc 2008-04-09 Modified Haml::Buffer#parse... 221 if prefix
222 class_name = "#{ prefix }_#{ class_name}"
223 id = "#{ prefix }_#{ id }"
224 end
a234dafb » nex3 2007-02-03 #foo[@person] now works as ... 225
d7030e9c » nex3 2007-06-02 [Haml] Preparse simple attr... 226 {'id' => id, 'class' => class_name}
89a10b9d » hcatlin 2006-10-14 Creating the next set of br... 227 end
00ef3f99 » nex3 2006-11-03 Better facilities for white... 228
18c7df96 » nex3 2007-03-30 Allow object_ref to be used... 229 # Changes a word from camel case to underscores.
230 # Based on the method of the same name in Rails' Inflector,
231 # but copied here so it'll run properly without Rails.
232 def underscore(camel_cased_word)
233 camel_cased_word.to_s.gsub(/::/, '_').
234 gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
235 gsub(/([a-z\d])([A-Z])/,'\1_\2').
236 tr("-", "_").
237 downcase
238 end
89a10b9d » hcatlin 2006-10-14 Creating the next set of br... 239 end
240 end