mack-haml 0.8.1 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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