mack-haml 0.8.1 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/lib/gems.rb +13 -0
  2. data/lib/gems/haml-2.0.4/VERSION +1 -0
  3. data/lib/gems/haml-2.0.4/bin/css2sass +7 -0
  4. data/lib/gems/haml-2.0.4/bin/haml +9 -0
  5. data/lib/gems/haml-2.0.4/bin/html2haml +7 -0
  6. data/lib/gems/haml-2.0.4/bin/sass +8 -0
  7. data/lib/gems/haml-2.0.4/lib/haml.rb +1040 -0
  8. data/lib/gems/haml-2.0.4/lib/haml/buffer.rb +239 -0
  9. data/lib/gems/haml-2.0.4/lib/haml/engine.rb +265 -0
  10. data/lib/gems/haml-2.0.4/lib/haml/error.rb +22 -0
  11. data/lib/gems/haml-2.0.4/lib/haml/exec.rb +364 -0
  12. data/lib/gems/haml-2.0.4/lib/haml/filters.rb +275 -0
  13. data/lib/gems/haml-2.0.4/lib/haml/helpers.rb +453 -0
  14. data/lib/gems/haml-2.0.4/lib/haml/helpers/action_view_extensions.rb +45 -0
  15. data/lib/gems/haml-2.0.4/lib/haml/helpers/action_view_mods.rb +179 -0
  16. data/lib/gems/haml-2.0.4/lib/haml/html.rb +227 -0
  17. data/lib/gems/haml-2.0.4/lib/haml/precompiler.rb +805 -0
  18. data/lib/gems/haml-2.0.4/lib/haml/template.rb +51 -0
  19. data/lib/gems/haml-2.0.4/lib/haml/template/patch.rb +58 -0
  20. data/lib/gems/haml-2.0.4/lib/haml/template/plugin.rb +72 -0
  21. data/lib/gems/haml-2.0.4/lib/sass.rb +863 -0
  22. data/lib/gems/haml-2.0.4/lib/sass/constant.rb +214 -0
  23. data/lib/gems/haml-2.0.4/lib/sass/constant/color.rb +101 -0
  24. data/lib/gems/haml-2.0.4/lib/sass/constant/literal.rb +54 -0
  25. data/lib/gems/haml-2.0.4/lib/sass/constant/nil.rb +9 -0
  26. data/lib/gems/haml-2.0.4/lib/sass/constant/number.rb +87 -0
  27. data/lib/gems/haml-2.0.4/lib/sass/constant/operation.rb +30 -0
  28. data/lib/gems/haml-2.0.4/lib/sass/constant/string.rb +22 -0
  29. data/lib/gems/haml-2.0.4/lib/sass/css.rb +394 -0
  30. data/lib/gems/haml-2.0.4/lib/sass/engine.rb +466 -0
  31. data/lib/gems/haml-2.0.4/lib/sass/error.rb +35 -0
  32. data/lib/gems/haml-2.0.4/lib/sass/plugin.rb +169 -0
  33. data/lib/gems/haml-2.0.4/lib/sass/plugin/merb.rb +56 -0
  34. data/lib/gems/haml-2.0.4/lib/sass/plugin/rails.rb +24 -0
  35. data/lib/gems/haml-2.0.4/lib/sass/tree/attr_node.rb +53 -0
  36. data/lib/gems/haml-2.0.4/lib/sass/tree/comment_node.rb +20 -0
  37. data/lib/gems/haml-2.0.4/lib/sass/tree/directive_node.rb +46 -0
  38. data/lib/gems/haml-2.0.4/lib/sass/tree/node.rb +42 -0
  39. data/lib/gems/haml-2.0.4/lib/sass/tree/rule_node.rb +89 -0
  40. data/lib/gems/haml-2.0.4/lib/sass/tree/value_node.rb +16 -0
  41. data/lib/gems/haml-2.0.4/rails/init.rb +1 -0
  42. data/lib/mack-haml.rb +1 -0
  43. metadata +65 -16
@@ -0,0 +1,239 @@
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
8
+
9
+ # The string that holds the compiled XHTML. This is aliased as
10
+ # _erbout for compatibility with ERB-specific code.
11
+ attr_accessor :buffer
12
+
13
+ # The options hash passed in from Haml::Engine.
14
+ attr_accessor :options
15
+
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
+
21
+ # See #active?
22
+ attr_writer :active
23
+
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
+
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
+
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
+
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
67
+
68
+ # Creates a new buffer.
69
+ def initialize(upper = nil, options = {})
70
+ @active = true
71
+ @upper = upper
72
+ @options = {
73
+ :attr_wrapper => "'",
74
+ :ugly => false,
75
+ :format => :xhtml
76
+ }.merge options
77
+ @buffer = ""
78
+ @tabulation = 0
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
83
+ end
84
+
85
+ # Renders +text+ with the proper tabulation. This also deals with
86
+ # making a possible one-line tag one line or not.
87
+ def push_text(text, dont_tab_up = false, tab_change = 0)
88
+ if @tabulation > 0 && !@options[:ugly]
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
94
+ end
95
+
96
+ @buffer << text
97
+ @real_tabs += tab_change
98
+ @dont_tab_up_next_line = false
99
+ end
100
+
101
+ # Properly formats the output of a script that was run in the
102
+ # instance_eval.
103
+ def push_script(result, preserve_script, in_tag = false, preserve_tag = false,
104
+ escape_html = false, nuke_inner_whitespace = false)
105
+ tabulation = @real_tabs
106
+
107
+ result = result.to_s.rstrip
108
+ result = html_escape(result) if escape_html
109
+
110
+ if preserve_tag
111
+ result = Haml::Helpers.preserve(result)
112
+ elsif preserve_script
113
+ result = Haml::Helpers.find_and_preserve(result, options[:preserve])
114
+ end
115
+
116
+ has_newline = result.include?("\n")
117
+ if in_tag && !nuke_inner_whitespace && (@options[:ugly] || !has_newline || preserve_tag)
118
+ @buffer << result
119
+ @real_tabs -= 1
120
+ return
121
+ end
122
+
123
+ @buffer << "\n" if in_tag && !nuke_inner_whitespace
124
+
125
+ # Precompiled tabulation may be wrong
126
+ if @tabulation > 0 && !in_tag
127
+ result = tabs + result
128
+ end
129
+
130
+ if has_newline && !@options[:ugly]
131
+ result = result.gsub "\n", "\n" + tabs(tabulation)
132
+
133
+ # Add tabulation if it wasn't precompiled
134
+ result = tabs(tabulation) + result if in_tag && !nuke_inner_whitespace
135
+ end
136
+ @buffer << "#{result}"
137
+ @buffer << "\n" unless nuke_inner_whitespace
138
+
139
+ if in_tag && !nuke_inner_whitespace
140
+ # We never get here if @options[:ugly] is true
141
+ @buffer << tabs(tabulation-1)
142
+ @real_tabs -= 1
143
+ end
144
+ nil
145
+ end
146
+
147
+ # Takes the various information about the opening tag for an
148
+ # element, formats it, and adds it to the buffer.
149
+ def open_tag(name, self_closing, try_one_line, preserve_tag, escape_html, class_id,
150
+ nuke_outer_whitespace, nuke_inner_whitespace, obj_ref, content, *attributes_hashes)
151
+ tabulation = @real_tabs
152
+
153
+ attributes = class_id
154
+ attributes_hashes.each do |old|
155
+ self.class.merge_attrs(attributes, old.inject({}) {|h, (key, val)| h[key.to_s] = val; h})
156
+ end
157
+ self.class.merge_attrs(attributes, parse_object_ref(obj_ref)) if obj_ref
158
+
159
+ if self_closing && xhtml?
160
+ str = " />" + (nuke_outer_whitespace ? "" : "\n")
161
+ else
162
+ str = ">" + ((if self_closing && html?
163
+ nuke_outer_whitespace
164
+ else
165
+ try_one_line || preserve_tag || nuke_inner_whitespace
166
+ end) ? "" : "\n")
167
+ end
168
+
169
+ attributes = Precompiler.build_attributes(html?, @options[:attr_wrapper], attributes)
170
+ @buffer << "#{nuke_outer_whitespace || @options[:ugly] ? '' : tabs(tabulation)}<#{name}#{attributes}#{str}"
171
+
172
+ if content
173
+ @buffer << "#{content}</#{name}>" << (nuke_outer_whitespace ? "" : "\n")
174
+ return
175
+ end
176
+
177
+ @real_tabs += 1 unless self_closing || nuke_inner_whitespace
178
+ end
179
+
180
+ def self.merge_attrs(to, from)
181
+ if to['id'] && from['id']
182
+ to['id'] << '_' << from.delete('id')
183
+ elsif to['id'] || from['id']
184
+ from['id'] ||= to['id']
185
+ end
186
+
187
+ if to['class'] && from['class']
188
+ # Make sure we don't duplicate class names
189
+ from['class'] = (from['class'].split(' ') | to['class'].split(' ')).join(' ')
190
+ elsif to['class'] || from['class']
191
+ from['class'] ||= to['class']
192
+ end
193
+
194
+ to.merge!(from)
195
+ end
196
+
197
+ private
198
+
199
+ # Some of these methods are exposed as public class methods
200
+ # so they can be re-used in helpers.
201
+
202
+ @@tab_cache = {}
203
+ # Gets <tt>count</tt> tabs. Mostly for internal use.
204
+ def tabs(count = 0)
205
+ tabs = [count + @tabulation, 0].max
206
+ @@tab_cache[tabs] ||= ' ' * tabs
207
+ end
208
+
209
+ # Takes an array of objects and uses the class and id of the first
210
+ # one to create an attributes hash.
211
+ # The second object, if present, is used as a prefix,
212
+ # just like you can do with dom_id() and dom_class() in Rails
213
+ def parse_object_ref(ref)
214
+ prefix = ref[1]
215
+ ref = ref[0]
216
+ # Let's make sure the value isn't nil. If it is, return the default Hash.
217
+ return {} if ref.nil?
218
+ class_name = underscore(ref.class)
219
+ id = "#{class_name}_#{ref.id || 'new'}"
220
+ if prefix
221
+ class_name = "#{ prefix }_#{ class_name}"
222
+ id = "#{ prefix }_#{ id }"
223
+ end
224
+
225
+ {'id' => id, 'class' => class_name}
226
+ end
227
+
228
+ # Changes a word from camel case to underscores.
229
+ # Based on the method of the same name in Rails' Inflector,
230
+ # but copied here so it'll run properly without Rails.
231
+ def underscore(camel_cased_word)
232
+ camel_cased_word.to_s.gsub(/::/, '_').
233
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
234
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
235
+ tr("-", "_").
236
+ downcase
237
+ end
238
+ end
239
+ end
@@ -0,0 +1,265 @@
1
+ require 'haml/helpers'
2
+ require 'haml/buffer'
3
+ require 'haml/precompiler'
4
+ require 'haml/filters'
5
+ require 'haml/error'
6
+
7
+ module Haml
8
+ # This is the class where all the parsing and processing of the Haml
9
+ # template is done. It can be directly used by the user by creating a
10
+ # new instance and calling <tt>to_html</tt> to render the template. For example:
11
+ #
12
+ # template = File.read('templates/really_cool_template.haml')
13
+ # haml_engine = Haml::Engine.new(template)
14
+ # output = haml_engine.to_html
15
+ # puts output
16
+ class Engine
17
+ include Precompiler
18
+
19
+ # Allow reading and writing of the options hash
20
+ attr :options, true
21
+
22
+ # This string contains the source code that is evaluated
23
+ # to produce the Haml document.
24
+ attr :precompiled, true
25
+
26
+ # True if the format is XHTML
27
+ def xhtml?
28
+ not html?
29
+ end
30
+
31
+ # True if the format is any flavor of HTML
32
+ def html?
33
+ html4? or html5?
34
+ end
35
+
36
+ # True if the format is HTML4
37
+ def html4?
38
+ @options[:format] == :html4
39
+ end
40
+
41
+ # True if the format is HTML5
42
+ def html5?
43
+ @options[:format] == :html5
44
+ end
45
+
46
+ # Creates a new instace of Haml::Engine that will compile the given
47
+ # template string when <tt>render</tt> is called.
48
+ # See the Haml module documentation for available options.
49
+ #
50
+ #--
51
+ # When adding options, remember to add information about them
52
+ # to lib/haml.rb!
53
+ #++
54
+ #
55
+ def initialize(template, options = {})
56
+ @options = {
57
+ :suppress_eval => false,
58
+ :attr_wrapper => "'",
59
+
60
+ # Don't forget to update the docs in lib/haml.rb if you update these
61
+ :autoclose => %w[meta img link br hr input area param col base],
62
+ :preserve => %w[textarea pre],
63
+
64
+ :filename => '(haml)',
65
+ :line => 1,
66
+ :ugly => false,
67
+ :format => :xhtml,
68
+ :escape_html => false
69
+ }
70
+ @options.merge! options
71
+ @index = 0
72
+
73
+ unless [:xhtml, :html4, :html5].include?(@options[:format])
74
+ raise Haml::Error, "Invalid format #{@options[:format].inspect}"
75
+ end
76
+
77
+ @template = template.rstrip + "\n-#\n-#"
78
+ @to_close_stack = []
79
+ @output_tabs = 0
80
+ @template_tabs = 0
81
+ @flat_spaces = -1
82
+ @flat = false
83
+ @newlines = 0
84
+ @precompiled = ''
85
+ @merged_text = ''
86
+ @tab_change = 0
87
+
88
+ if @template =~ /\A(\s*\n)*[ \t]+\S/
89
+ raise SyntaxError.new("Indenting at the beginning of the document is illegal.", ($1 || "").count("\n"))
90
+ end
91
+
92
+ if @options[:filters]
93
+ warn <<END
94
+ DEPRECATION WARNING:
95
+ The Haml :filters option is deprecated and will be removed in version 2.2.
96
+ Filters are now automatically registered.
97
+ END
98
+ end
99
+
100
+ precompile
101
+ rescue Haml::Error => e
102
+ e.backtrace.unshift "#{@options[:filename]}:#{(e.line ? e.line + 1 : @index) + @options[:line] - 1}" if @index
103
+ raise
104
+ end
105
+
106
+ # Processes the template and returns the result as a string.
107
+ #
108
+ # +scope+ is the context in which the template is evaluated.
109
+ # If it's a Binding or Proc object,
110
+ # Haml uses it as the second argument to Kernel#eval;
111
+ # otherwise, Haml just uses its #instance_eval context.
112
+ #
113
+ # Note that Haml modifies the evaluation context
114
+ # (either the scope object or the "self" object of the scope binding).
115
+ # It extends Haml::Helpers, and various instance variables are set
116
+ # (all prefixed with "haml").
117
+ # For example:
118
+ #
119
+ # s = "foobar"
120
+ # Haml::Engine.new("%p= upcase").render(s) #=> "<p>FOOBAR</p>"
121
+ #
122
+ # # s now extends Haml::Helpers
123
+ # s.responds_to?(:html_attrs) #=> true
124
+ #
125
+ # +locals+ is a hash of local variables to make available to the template.
126
+ # For example:
127
+ #
128
+ # Haml::Engine.new("%p= foo").render(Object.new, :foo => "Hello, world!") #=> "<p>Hello, world!</p>"
129
+ #
130
+ # If a block is passed to render,
131
+ # that block is run when +yield+ is called
132
+ # within the template.
133
+ #
134
+ # Due to some Ruby quirks,
135
+ # if scope is a Binding or Proc object and a block is given,
136
+ # the evaluation context may not be quite what the user expects.
137
+ # In particular, it's equivalent to passing <tt>eval("self", scope)</tt> as scope.
138
+ # This won't have an effect in most cases,
139
+ # but if you're relying on local variables defined in the context of scope,
140
+ # they won't work.
141
+ def render(scope = Object.new, locals = {}, &block)
142
+ buffer = Haml::Buffer.new(scope.instance_variable_get('@haml_buffer'), options_for_buffer)
143
+
144
+ if scope.is_a?(Binding) || scope.is_a?(Proc)
145
+ scope_object = eval("self", scope)
146
+ scope = scope_object.instance_eval{binding} if block_given?
147
+ else
148
+ scope_object = scope
149
+ scope = scope_object.instance_eval{binding}
150
+ end
151
+
152
+ set_locals(locals.merge(:_hamlout => buffer, :_erbout => buffer.buffer), scope, scope_object)
153
+
154
+ scope_object.instance_eval do
155
+ extend Haml::Helpers
156
+ @haml_buffer = buffer
157
+ end
158
+
159
+ eval(@precompiled, scope, @options[:filename], @options[:line])
160
+
161
+ # Get rid of the current buffer
162
+ scope_object.instance_eval do
163
+ @haml_buffer = buffer.upper
164
+ end
165
+
166
+ buffer.buffer
167
+ end
168
+ alias_method :to_html, :render
169
+
170
+ # Returns a proc that, when called,
171
+ # renders the template and returns the result as a string.
172
+ #
173
+ # +scope+ works the same as it does for render.
174
+ #
175
+ # The first argument of the returned proc is a hash of local variable names to values.
176
+ # However, due to an unfortunate Ruby quirk,
177
+ # the local variables which can be assigned must be pre-declared.
178
+ # This is done with the +local_names+ argument.
179
+ # For example:
180
+ #
181
+ # # This works
182
+ # Haml::Engine.new("%p= foo").render_proc(Object.new, :foo).call :foo => "Hello!"
183
+ # #=> "<p>Hello!</p>"
184
+ #
185
+ # # This doesn't
186
+ # Haml::Engine.new("%p= foo").render_proc.call :foo => "Hello!"
187
+ # #=> NameError: undefined local variable or method `foo'
188
+ #
189
+ # The proc doesn't take a block;
190
+ # any yields in the template will fail.
191
+ def render_proc(scope = Object.new, *local_names)
192
+ if scope.is_a?(Binding) || scope.is_a?(Proc)
193
+ scope_object = eval("self", scope)
194
+ else
195
+ scope_object = scope
196
+ scope = scope_object.instance_eval{binding}
197
+ end
198
+
199
+ eval("Proc.new { |*_haml_locals| _haml_locals = _haml_locals[0] || {};" +
200
+ precompiled_with_ambles(local_names) + "}\n", scope, @options[:filename], @options[:line])
201
+ end
202
+
203
+ # Defines a method on +object+
204
+ # with the given name
205
+ # that renders the template and returns the result as a string.
206
+ #
207
+ # If +object+ is a class or module,
208
+ # the method will instead by defined as an instance method.
209
+ # For example:
210
+ #
211
+ # t = Time.now
212
+ # Haml::Engine.new("%p\n Today's date is\n .date= self.to_s").def_method(t, :render)
213
+ # t.render #=> "<p>\n Today's date is\n <div class='date'>Fri Nov 23 18:28:29 -0800 2007</div>\n</p>\n"
214
+ #
215
+ # Haml::Engine.new(".upcased= upcase").def_method(String, :upcased_div)
216
+ # "foobar".upcased_div #=> "<div class='upcased'>FOOBAR</div>\n"
217
+ #
218
+ # The first argument of the defined method is a hash of local variable names to values.
219
+ # However, due to an unfortunate Ruby quirk,
220
+ # the local variables which can be assigned must be pre-declared.
221
+ # This is done with the +local_names+ argument.
222
+ # For example:
223
+ #
224
+ # # This works
225
+ # obj = Object.new
226
+ # Haml::Engine.new("%p= foo").def_method(obj, :render, :foo)
227
+ # obj.render(:foo => "Hello!") #=> "<p>Hello!</p>"
228
+ #
229
+ # # This doesn't
230
+ # obj = Object.new
231
+ # Haml::Engine.new("%p= foo").def_method(obj, :render)
232
+ # obj.render(:foo => "Hello!") #=> NameError: undefined local variable or method `foo'
233
+ #
234
+ # Note that Haml modifies the evaluation context
235
+ # (either the scope object or the "self" object of the scope binding).
236
+ # It extends Haml::Helpers, and various instance variables are set
237
+ # (all prefixed with "haml").
238
+ def def_method(object, name, *local_names)
239
+ method = object.is_a?(Module) ? :module_eval : :instance_eval
240
+
241
+ object.send(method, "def #{name}(_haml_locals = {}); #{precompiled_with_ambles(local_names)}; end",
242
+ @options[:filename], @options[:line])
243
+ end
244
+
245
+ private
246
+
247
+ def set_locals(locals, scope, scope_object)
248
+ scope_object.send(:instance_variable_set, '@_haml_locals', locals)
249
+ set_locals = locals.keys.map { |k| "#{k} = @_haml_locals[#{k.inspect}]" }.join("\n")
250
+ eval(set_locals, scope)
251
+ end
252
+
253
+ # Returns a hash of options that Haml::Buffer cares about.
254
+ # This should remain loadable from #inspect.
255
+ def options_for_buffer
256
+ {
257
+ :autoclose => @options[:autoclose],
258
+ :preserve => @options[:preserve],
259
+ :attr_wrapper => @options[:attr_wrapper],
260
+ :ugly => @options[:ugly],
261
+ :format => @options[:format]
262
+ }
263
+ end
264
+ end
265
+ end