jwhitmire-haml 2.1.0.1
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.
- data/README.rdoc +332 -0
- data/bin/css2sass +7 -0
- data/bin/haml +9 -0
- data/bin/html2haml +7 -0
- data/bin/sass +8 -0
- data/lib/haml/buffer.rb +255 -0
- data/lib/haml/engine.rb +268 -0
- data/lib/haml/error.rb +22 -0
- data/lib/haml/exec.rb +395 -0
- data/lib/haml/filters.rb +276 -0
- data/lib/haml/helpers/action_view_extensions.rb +45 -0
- data/lib/haml/helpers/action_view_mods.rb +181 -0
- data/lib/haml/helpers.rb +468 -0
- data/lib/haml/html.rb +218 -0
- data/lib/haml/precompiler.rb +889 -0
- data/lib/haml/shared.rb +45 -0
- data/lib/haml/template/patch.rb +58 -0
- data/lib/haml/template/plugin.rb +72 -0
- data/lib/haml/template.rb +51 -0
- data/lib/haml/util.rb +77 -0
- data/lib/haml/version.rb +47 -0
- data/lib/haml.rb +1042 -0
- data/lib/sass/css.rb +388 -0
- data/lib/sass/engine.rb +499 -0
- data/lib/sass/environment.rb +33 -0
- data/lib/sass/error.rb +35 -0
- data/lib/sass/plugin/merb.rb +56 -0
- data/lib/sass/plugin/rails.rb +24 -0
- data/lib/sass/plugin.rb +203 -0
- data/lib/sass/repl.rb +51 -0
- data/lib/sass/script/bool.rb +13 -0
- data/lib/sass/script/color.rb +97 -0
- data/lib/sass/script/funcall.rb +28 -0
- data/lib/sass/script/functions.rb +122 -0
- data/lib/sass/script/lexer.rb +152 -0
- data/lib/sass/script/literal.rb +60 -0
- data/lib/sass/script/number.rb +231 -0
- data/lib/sass/script/operation.rb +30 -0
- data/lib/sass/script/parser.rb +142 -0
- data/lib/sass/script/string.rb +42 -0
- data/lib/sass/script/unary_operation.rb +21 -0
- data/lib/sass/script/variable.rb +20 -0
- data/lib/sass/script.rb +38 -0
- data/lib/sass/tree/attr_node.rb +64 -0
- data/lib/sass/tree/comment_node.rb +34 -0
- data/lib/sass/tree/debug_node.rb +22 -0
- data/lib/sass/tree/directive_node.rb +50 -0
- data/lib/sass/tree/file_node.rb +27 -0
- data/lib/sass/tree/for_node.rb +29 -0
- data/lib/sass/tree/if_node.rb +27 -0
- data/lib/sass/tree/mixin_def_node.rb +18 -0
- data/lib/sass/tree/mixin_node.rb +34 -0
- data/lib/sass/tree/node.rb +99 -0
- data/lib/sass/tree/rule_node.rb +120 -0
- data/lib/sass/tree/variable_node.rb +24 -0
- data/lib/sass/tree/while_node.rb +20 -0
- data/lib/sass.rb +1062 -0
- data/test/benchmark.rb +99 -0
- data/test/haml/engine_test.rb +734 -0
- data/test/haml/helper_test.rb +224 -0
- data/test/haml/html2haml_test.rb +92 -0
- data/test/haml/markaby/standard.mab +52 -0
- data/test/haml/mocks/article.rb +6 -0
- data/test/haml/results/content_for_layout.xhtml +15 -0
- data/test/haml/results/eval_suppressed.xhtml +9 -0
- data/test/haml/results/filters.xhtml +62 -0
- data/test/haml/results/helpers.xhtml +93 -0
- data/test/haml/results/helpful.xhtml +10 -0
- data/test/haml/results/just_stuff.xhtml +68 -0
- data/test/haml/results/list.xhtml +12 -0
- data/test/haml/results/nuke_inner_whitespace.xhtml +40 -0
- data/test/haml/results/nuke_outer_whitespace.xhtml +148 -0
- data/test/haml/results/original_engine.xhtml +20 -0
- data/test/haml/results/partial_layout.xhtml +5 -0
- data/test/haml/results/partials.xhtml +21 -0
- data/test/haml/results/render_layout.xhtml +3 -0
- data/test/haml/results/silent_script.xhtml +74 -0
- data/test/haml/results/standard.xhtml +42 -0
- data/test/haml/results/tag_parsing.xhtml +23 -0
- data/test/haml/results/very_basic.xhtml +5 -0
- data/test/haml/results/whitespace_handling.xhtml +89 -0
- data/test/haml/rhtml/_av_partial_1.rhtml +12 -0
- data/test/haml/rhtml/_av_partial_2.rhtml +8 -0
- data/test/haml/rhtml/action_view.rhtml +62 -0
- data/test/haml/rhtml/standard.rhtml +54 -0
- data/test/haml/template_test.rb +204 -0
- data/test/haml/templates/_av_partial_1.haml +9 -0
- data/test/haml/templates/_av_partial_1_ugly.haml +9 -0
- data/test/haml/templates/_av_partial_2.haml +5 -0
- data/test/haml/templates/_av_partial_2_ugly.haml +5 -0
- data/test/haml/templates/_layout.erb +3 -0
- data/test/haml/templates/_layout_for_partial.haml +3 -0
- data/test/haml/templates/_partial.haml +8 -0
- data/test/haml/templates/_text_area.haml +3 -0
- data/test/haml/templates/action_view.haml +47 -0
- data/test/haml/templates/action_view_ugly.haml +47 -0
- data/test/haml/templates/breakage.haml +8 -0
- data/test/haml/templates/content_for_layout.haml +10 -0
- data/test/haml/templates/eval_suppressed.haml +11 -0
- data/test/haml/templates/filters.haml +66 -0
- data/test/haml/templates/helpers.haml +95 -0
- data/test/haml/templates/helpful.haml +11 -0
- data/test/haml/templates/just_stuff.haml +83 -0
- data/test/haml/templates/list.haml +12 -0
- data/test/haml/templates/nuke_inner_whitespace.haml +32 -0
- data/test/haml/templates/nuke_outer_whitespace.haml +144 -0
- data/test/haml/templates/original_engine.haml +17 -0
- data/test/haml/templates/partial_layout.haml +3 -0
- data/test/haml/templates/partialize.haml +1 -0
- data/test/haml/templates/partials.haml +12 -0
- data/test/haml/templates/render_layout.haml +2 -0
- data/test/haml/templates/silent_script.haml +40 -0
- data/test/haml/templates/standard.haml +42 -0
- data/test/haml/templates/standard_ugly.haml +1 -0
- data/test/haml/templates/tag_parsing.haml +21 -0
- data/test/haml/templates/very_basic.haml +4 -0
- data/test/haml/templates/whitespace_handling.haml +87 -0
- data/test/linked_rails.rb +12 -0
- data/test/sass/css2sass_test.rb +193 -0
- data/test/sass/engine_test.rb +786 -0
- data/test/sass/functions_test.rb +96 -0
- data/test/sass/more_results/more1.css +9 -0
- data/test/sass/more_results/more1_with_line_comments.css +26 -0
- data/test/sass/more_results/more_import.css +29 -0
- data/test/sass/more_templates/_more_partial.sass +2 -0
- data/test/sass/more_templates/more1.sass +23 -0
- data/test/sass/more_templates/more_import.sass +11 -0
- data/test/sass/plugin_test.rb +208 -0
- data/test/sass/results/alt.css +4 -0
- data/test/sass/results/basic.css +9 -0
- data/test/sass/results/compact.css +5 -0
- data/test/sass/results/complex.css +87 -0
- data/test/sass/results/compressed.css +1 -0
- data/test/sass/results/expanded.css +19 -0
- data/test/sass/results/import.css +29 -0
- data/test/sass/results/line_numbers.css +49 -0
- data/test/sass/results/mixins.css +95 -0
- data/test/sass/results/multiline.css +24 -0
- data/test/sass/results/nested.css +22 -0
- data/test/sass/results/parent_ref.css +13 -0
- data/test/sass/results/script.css +16 -0
- data/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
- data/test/sass/results/subdir/subdir.css +3 -0
- data/test/sass/results/units.css +11 -0
- data/test/sass/script_test.rb +153 -0
- data/test/sass/templates/_partial.sass +2 -0
- data/test/sass/templates/alt.sass +16 -0
- data/test/sass/templates/basic.sass +23 -0
- data/test/sass/templates/bork.sass +2 -0
- data/test/sass/templates/bork2.sass +2 -0
- data/test/sass/templates/compact.sass +17 -0
- data/test/sass/templates/complex.sass +309 -0
- data/test/sass/templates/compressed.sass +15 -0
- data/test/sass/templates/expanded.sass +17 -0
- data/test/sass/templates/import.sass +11 -0
- data/test/sass/templates/importee.sass +19 -0
- data/test/sass/templates/line_numbers.sass +13 -0
- data/test/sass/templates/mixins.sass +76 -0
- data/test/sass/templates/multiline.sass +20 -0
- data/test/sass/templates/nested.sass +25 -0
- data/test/sass/templates/parent_ref.sass +25 -0
- data/test/sass/templates/script.sass +101 -0
- data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
- data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
- data/test/sass/templates/subdir/subdir.sass +6 -0
- data/test/sass/templates/units.sass +11 -0
- data/test/test_helper.rb +21 -0
- metadata +245 -0
data/lib/haml/helpers.rb
ADDED
@@ -0,0 +1,468 @@
|
|
1
|
+
require 'haml/helpers/action_view_mods'
|
2
|
+
require 'haml/helpers/action_view_extensions'
|
3
|
+
|
4
|
+
module Haml
|
5
|
+
# This module contains various helpful methods to make it easier to do
|
6
|
+
# various tasks. Haml::Helpers is automatically included in the context
|
7
|
+
# that a Haml template is parsed in, so all these methods are at your
|
8
|
+
# disposal from within the template.
|
9
|
+
module Helpers
|
10
|
+
self.extend self
|
11
|
+
|
12
|
+
@@action_view_defined = defined?(ActionView)
|
13
|
+
@@force_no_action_view = false
|
14
|
+
|
15
|
+
# Returns whether or not ActionView is installed on the system.
|
16
|
+
def self.action_view?
|
17
|
+
@@action_view_defined
|
18
|
+
end
|
19
|
+
|
20
|
+
# Note: this does *not* need to be called
|
21
|
+
# when using Haml helpers normally
|
22
|
+
# in Rails.
|
23
|
+
#
|
24
|
+
# Initializes the current object
|
25
|
+
# as though it were in the same context
|
26
|
+
# as a normal ActionView rendering
|
27
|
+
# using Haml.
|
28
|
+
# This is useful if you want to use the helpers in a context
|
29
|
+
# other than the normal setup with ActionView.
|
30
|
+
# For example:
|
31
|
+
#
|
32
|
+
# context = Object.new
|
33
|
+
# class << context
|
34
|
+
# include Haml::Helpers
|
35
|
+
# end
|
36
|
+
# context.init_haml_helpers
|
37
|
+
# context.haml_tag :p, "Stuff"
|
38
|
+
#
|
39
|
+
def init_haml_helpers
|
40
|
+
@haml_buffer = Haml::Buffer.new(@haml_buffer, Haml::Engine.new('').send(:options_for_buffer))
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
|
44
|
+
# call-seq:
|
45
|
+
# non_haml { ... }
|
46
|
+
#
|
47
|
+
# Runs a block of code in a non-Haml context
|
48
|
+
# (i.e. #is_haml? will return false).
|
49
|
+
#
|
50
|
+
# This is mainly useful for rendering sub-templates such as partials in a non-Haml language,
|
51
|
+
# particularly where helpers may behave differently when run from Haml.
|
52
|
+
#
|
53
|
+
# Note that this is automatically applied to Rails partials.
|
54
|
+
def non_haml
|
55
|
+
was_active = @haml_buffer.active?
|
56
|
+
@haml_buffer.active = false
|
57
|
+
yield
|
58
|
+
ensure
|
59
|
+
@haml_buffer.active = was_active
|
60
|
+
end
|
61
|
+
|
62
|
+
# call-seq:
|
63
|
+
# find_and_preserve(input, tags = haml_buffer.options[:preserve])
|
64
|
+
# find_and_preserve {...}
|
65
|
+
#
|
66
|
+
# Uses preserve to convert any newlines inside whitespace-sensitive tags
|
67
|
+
# into the HTML entities for endlines.
|
68
|
+
# @tags@ is an array of tags to preserve.
|
69
|
+
# It defaults to the value of the <tt>:preserve</tt> option.
|
70
|
+
def find_and_preserve(input = '', tags = haml_buffer.options[:preserve], &block)
|
71
|
+
return find_and_preserve(capture_haml(&block)) if block
|
72
|
+
|
73
|
+
input = input.to_s
|
74
|
+
input.gsub(/<(#{tags.map(&Regexp.method(:escape)).join('|')})([^>]*)>(.*?)(<\/\1>)/im) do
|
75
|
+
"<#{$1}#{$2}>#{preserve($3)}</#{$1}>"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# call-seq:
|
80
|
+
# preserve(input)
|
81
|
+
# preserve {...}
|
82
|
+
#
|
83
|
+
# Takes any string, finds all the endlines and converts them to
|
84
|
+
# HTML entities for endlines so they'll render correctly in
|
85
|
+
# whitespace-sensitive tags without screwing up the indentation.
|
86
|
+
def preserve(input = '', &block)
|
87
|
+
return preserve(capture_haml(&block)) if block
|
88
|
+
|
89
|
+
input.chomp("\n").gsub(/\n/, '
').gsub(/\r/, '')
|
90
|
+
end
|
91
|
+
|
92
|
+
alias_method :flatten, :preserve
|
93
|
+
|
94
|
+
# Takes an Enumerable object and a block
|
95
|
+
# and iterates over the object,
|
96
|
+
# yielding each element to a Haml block
|
97
|
+
# and putting the result into <tt><li></tt> elements.
|
98
|
+
# This creates a list of the results of the block.
|
99
|
+
# For example:
|
100
|
+
#
|
101
|
+
# = list_of([['hello'], ['yall']]) do |i|
|
102
|
+
# = i[0]
|
103
|
+
#
|
104
|
+
# Produces:
|
105
|
+
#
|
106
|
+
# <li>hello</li>
|
107
|
+
# <li>yall</li>
|
108
|
+
#
|
109
|
+
# And
|
110
|
+
#
|
111
|
+
# = list_of({:title => 'All the stuff', :description => 'A book about all the stuff.'}) do |key, val|
|
112
|
+
# %h3= key.humanize
|
113
|
+
# %p= val
|
114
|
+
#
|
115
|
+
# Produces:
|
116
|
+
#
|
117
|
+
# <li>
|
118
|
+
# <h3>Title</h3>
|
119
|
+
# <p>All the stuff</p>
|
120
|
+
# </li>
|
121
|
+
# <li>
|
122
|
+
# <h3>Description</h3>
|
123
|
+
# <p>A book about all the stuff.</p>
|
124
|
+
# </li>
|
125
|
+
#
|
126
|
+
def list_of(array, &block) # :yields: item
|
127
|
+
to_return = array.collect do |i|
|
128
|
+
result = capture_haml(i, &block)
|
129
|
+
|
130
|
+
if result.count("\n") > 1
|
131
|
+
result.gsub!("\n", "\n ")
|
132
|
+
result = "\n #{result.strip}\n"
|
133
|
+
else
|
134
|
+
result.strip!
|
135
|
+
end
|
136
|
+
|
137
|
+
"<li>#{result}</li>"
|
138
|
+
end
|
139
|
+
to_return.join("\n")
|
140
|
+
end
|
141
|
+
|
142
|
+
# Returns a hash containing default assignments for the xmlns and xml:lang
|
143
|
+
# attributes of the <tt>html</tt> HTML element.
|
144
|
+
# It also takes an optional argument for the value of xml:lang and lang,
|
145
|
+
# which defaults to 'en-US'.
|
146
|
+
# For example,
|
147
|
+
#
|
148
|
+
# %html{html_attrs}
|
149
|
+
#
|
150
|
+
# becomes
|
151
|
+
#
|
152
|
+
# <html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en-US' lang='en-US'>
|
153
|
+
#
|
154
|
+
def html_attrs(lang = 'en-US')
|
155
|
+
{:xmlns => "http://www.w3.org/1999/xhtml", 'xml:lang' => lang, :lang => lang}
|
156
|
+
end
|
157
|
+
|
158
|
+
# Increments the number of tabs the buffer automatically adds
|
159
|
+
# to the lines of the template.
|
160
|
+
# For example:
|
161
|
+
#
|
162
|
+
# %h1 foo
|
163
|
+
# - tab_up
|
164
|
+
# %p bar
|
165
|
+
# - tab_down
|
166
|
+
# %strong baz
|
167
|
+
#
|
168
|
+
# Produces:
|
169
|
+
#
|
170
|
+
# <h1>foo</h1>
|
171
|
+
# <p>bar</p>
|
172
|
+
# <strong>baz</strong>
|
173
|
+
#
|
174
|
+
def tab_up(i = 1)
|
175
|
+
haml_buffer.tabulation += i
|
176
|
+
end
|
177
|
+
|
178
|
+
# Decrements the number of tabs the buffer automatically adds
|
179
|
+
# to the lines of the template.
|
180
|
+
#
|
181
|
+
# See also tab_up.
|
182
|
+
def tab_down(i = 1)
|
183
|
+
haml_buffer.tabulation -= i
|
184
|
+
end
|
185
|
+
|
186
|
+
# Surrounds the given block of Haml code with the given characters,
|
187
|
+
# with no whitespace in between.
|
188
|
+
# For example:
|
189
|
+
#
|
190
|
+
# = surround '(', ')' do
|
191
|
+
# %a{:href => "food"} chicken
|
192
|
+
#
|
193
|
+
# Produces:
|
194
|
+
#
|
195
|
+
# (<a href='food'>chicken</a>)
|
196
|
+
#
|
197
|
+
# and
|
198
|
+
#
|
199
|
+
# = surround '*' do
|
200
|
+
# %strong angry
|
201
|
+
#
|
202
|
+
# Produces:
|
203
|
+
#
|
204
|
+
# *<strong>angry</strong>*
|
205
|
+
#
|
206
|
+
def surround(front, back = nil, &block)
|
207
|
+
back ||= front
|
208
|
+
output = capture_haml(&block)
|
209
|
+
|
210
|
+
"#{front}#{output.chomp}#{back}\n"
|
211
|
+
end
|
212
|
+
|
213
|
+
# Prepends the given character to the beginning of the Haml block,
|
214
|
+
# with no whitespace between.
|
215
|
+
# For example:
|
216
|
+
#
|
217
|
+
# = precede '*' do
|
218
|
+
# %span.small Not really
|
219
|
+
#
|
220
|
+
# Produces:
|
221
|
+
#
|
222
|
+
# *<span class='small'>Not really</span>
|
223
|
+
#
|
224
|
+
def precede(char, &block)
|
225
|
+
"#{char}#{capture_haml(&block).chomp}\n"
|
226
|
+
end
|
227
|
+
|
228
|
+
# Appends the given character to the end of the Haml block,
|
229
|
+
# with no whitespace between.
|
230
|
+
# For example:
|
231
|
+
#
|
232
|
+
# click
|
233
|
+
# = succeed '.' do
|
234
|
+
# %a{:href=>"thing"} here
|
235
|
+
#
|
236
|
+
# Produces:
|
237
|
+
#
|
238
|
+
# click
|
239
|
+
# <a href='thing'>here</a>.
|
240
|
+
#
|
241
|
+
def succeed(char, &block)
|
242
|
+
"#{capture_haml(&block).chomp}#{char}\n"
|
243
|
+
end
|
244
|
+
|
245
|
+
# Captures the result of the given block of Haml code,
|
246
|
+
# gets rid of the excess indentation,
|
247
|
+
# and returns it as a string.
|
248
|
+
# For example, after the following,
|
249
|
+
#
|
250
|
+
# .foo
|
251
|
+
# - foo = capture_haml(13) do |a|
|
252
|
+
# %p= a
|
253
|
+
#
|
254
|
+
# the local variable <tt>foo</tt> would be assigned to "<p>13</p>\n".
|
255
|
+
#
|
256
|
+
def capture_haml(*args, &block)
|
257
|
+
buffer = eval('_hamlout', block.binding) rescue haml_buffer
|
258
|
+
with_haml_buffer(buffer) do
|
259
|
+
position = haml_buffer.buffer.length
|
260
|
+
|
261
|
+
block.call(*args)
|
262
|
+
|
263
|
+
captured = haml_buffer.buffer.slice!(position..-1).split(/^/)
|
264
|
+
|
265
|
+
min_tabs = nil
|
266
|
+
captured.each do |line|
|
267
|
+
tabs = line.index(/[^ ]/) || line.length
|
268
|
+
min_tabs ||= tabs
|
269
|
+
min_tabs = min_tabs > tabs ? tabs : min_tabs
|
270
|
+
end
|
271
|
+
|
272
|
+
captured.map do |line|
|
273
|
+
line[min_tabs..-1]
|
274
|
+
end.join
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
def puts(*args) # :nodoc:
|
279
|
+
warn <<END
|
280
|
+
DEPRECATION WARNING:
|
281
|
+
The Haml #puts helper is deprecated and will be removed in version 2.4.
|
282
|
+
Use the #haml_concat helper instead.
|
283
|
+
END
|
284
|
+
haml_concat *args
|
285
|
+
end
|
286
|
+
|
287
|
+
# Outputs text directly to the Haml buffer, with the proper tabulation
|
288
|
+
def haml_concat(text = "")
|
289
|
+
haml_buffer.buffer << haml_indent << text.to_s << "\n"
|
290
|
+
nil
|
291
|
+
end
|
292
|
+
|
293
|
+
# Returns the string that should be used to indent the current line
|
294
|
+
def haml_indent
|
295
|
+
' ' * haml_buffer.tabulation
|
296
|
+
end
|
297
|
+
|
298
|
+
#
|
299
|
+
# call-seq:
|
300
|
+
# haml_tag(name, *flags, attributes = {}) {...}
|
301
|
+
# haml_tag(name, text, *flags, attributes = {}) {...}
|
302
|
+
#
|
303
|
+
# Creates an HTML tag with the given name and optionally text and attributes.
|
304
|
+
# Can take a block that will be executed
|
305
|
+
# between when the opening and closing tags are output.
|
306
|
+
# If the block is a Haml block or outputs text using haml_concat,
|
307
|
+
# the text will be properly indented.
|
308
|
+
#
|
309
|
+
# <tt>flags</tt> is a list of symbol flags
|
310
|
+
# like those that can be put at the end of a Haml tag
|
311
|
+
# (<tt>:/</tt>, <tt>:<</tt>, and <tt>:></tt>).
|
312
|
+
# Currently, only <tt>:/</tt> and <tt>:<</tt> are supported.
|
313
|
+
#
|
314
|
+
# For example,
|
315
|
+
#
|
316
|
+
# haml_tag :table do
|
317
|
+
# haml_tag :tr do
|
318
|
+
# haml_tag :td, {:class => 'cell'} do
|
319
|
+
# haml_tag :strong, "strong!"
|
320
|
+
# haml_concat "data"
|
321
|
+
# end
|
322
|
+
# haml_tag :td do
|
323
|
+
# haml_concat "more_data"
|
324
|
+
# end
|
325
|
+
# end
|
326
|
+
# end
|
327
|
+
#
|
328
|
+
# outputs
|
329
|
+
#
|
330
|
+
# <table>
|
331
|
+
# <tr>
|
332
|
+
# <td class='cell'>
|
333
|
+
# <strong>
|
334
|
+
# strong!
|
335
|
+
# </strong>
|
336
|
+
# data
|
337
|
+
# </td>
|
338
|
+
# <td>
|
339
|
+
# more_data
|
340
|
+
# </td>
|
341
|
+
# </tr>
|
342
|
+
# </table>
|
343
|
+
#
|
344
|
+
def haml_tag(name, *rest, &block)
|
345
|
+
name = name.to_s
|
346
|
+
text = rest.shift.to_s unless [Symbol, Hash, NilClass].any? {|t| rest.first.is_a? t}
|
347
|
+
flags = []
|
348
|
+
flags << rest.shift while rest.first.is_a? Symbol
|
349
|
+
attributes = Haml::Precompiler.build_attributes(haml_buffer.html?,
|
350
|
+
haml_buffer.options[:attr_wrapper],
|
351
|
+
rest.shift || {})
|
352
|
+
|
353
|
+
if text.nil? && block.nil? && (haml_buffer.options[:autoclose].include?(name) || flags.include?(:/))
|
354
|
+
haml_concat "<#{name}#{attributes} />"
|
355
|
+
return nil
|
356
|
+
end
|
357
|
+
|
358
|
+
if flags.include?(:/)
|
359
|
+
raise Error.new("Self-closing tags can't have content.") if text
|
360
|
+
raise Error.new("Illegal nesting: nesting within a self-closing tag is illegal.") if block
|
361
|
+
end
|
362
|
+
|
363
|
+
tag = "<#{name}#{attributes}>"
|
364
|
+
if block.nil?
|
365
|
+
tag << text.to_s << "</#{name}>"
|
366
|
+
haml_concat tag
|
367
|
+
return
|
368
|
+
end
|
369
|
+
|
370
|
+
if text
|
371
|
+
raise Error.new("Illegal nesting: content can't be both given to haml_tag :#{name} and nested within it.")
|
372
|
+
end
|
373
|
+
|
374
|
+
if flags.include?(:<)
|
375
|
+
tag << capture_haml(&block).strip << "</#{name}>"
|
376
|
+
haml_concat tag
|
377
|
+
return
|
378
|
+
end
|
379
|
+
|
380
|
+
haml_concat tag
|
381
|
+
tab_up
|
382
|
+
block.call
|
383
|
+
tab_down
|
384
|
+
haml_concat "</#{name}>"
|
385
|
+
<<MESSAGE
|
386
|
+
<h1><code>haml_tag</code> outputs directly to the Haml template.
|
387
|
+
Disregard its return value and use the <code>-</code> operator.</h1>
|
388
|
+
MESSAGE
|
389
|
+
end
|
390
|
+
|
391
|
+
# Characters that need to be escaped to HTML entities from user input
|
392
|
+
HTML_ESCAPE = { '&'=>'&', '<'=>'<', '>'=>'>', '"'=>'"', "'"=>''', }
|
393
|
+
|
394
|
+
# Returns a copy of <tt>text</tt> with ampersands, angle brackets and quotes
|
395
|
+
# escaped into HTML entities.
|
396
|
+
def html_escape(text)
|
397
|
+
text.to_s.gsub(/[\"><&]/) { |s| HTML_ESCAPE[s] }
|
398
|
+
end
|
399
|
+
|
400
|
+
# Escapes HTML entities in <tt>text</tt>, but without escaping an ampersand
|
401
|
+
# that is already part of an escaped entity.
|
402
|
+
def escape_once(text)
|
403
|
+
text.to_s.gsub(/[\"><]|&(?!([a-zA-Z]+|(#\d+));)/) { |s| HTML_ESCAPE[s] }
|
404
|
+
end
|
405
|
+
|
406
|
+
# Returns whether or not the current template is a Haml template.
|
407
|
+
#
|
408
|
+
# This function, unlike other Haml::Helpers functions,
|
409
|
+
# also works in other ActionView templates,
|
410
|
+
# where it will always return false.
|
411
|
+
def is_haml?
|
412
|
+
!@haml_buffer.nil? && @haml_buffer.active?
|
413
|
+
end
|
414
|
+
|
415
|
+
# Returns whether or not +block+ is defined directly in a Haml template.
|
416
|
+
def block_is_haml?(block)
|
417
|
+
eval('_hamlout', block.binding)
|
418
|
+
true
|
419
|
+
rescue
|
420
|
+
false
|
421
|
+
end
|
422
|
+
|
423
|
+
private
|
424
|
+
|
425
|
+
# call-seq:
|
426
|
+
# with_haml_buffer(buffer) {...}
|
427
|
+
#
|
428
|
+
# Runs the block with the given buffer as the currently active buffer.
|
429
|
+
def with_haml_buffer(buffer)
|
430
|
+
@haml_buffer, old_buffer = buffer, @haml_buffer
|
431
|
+
old_buffer.active, was_active = false, old_buffer.active? if old_buffer
|
432
|
+
@haml_buffer.active = true
|
433
|
+
yield
|
434
|
+
ensure
|
435
|
+
@haml_buffer.active = false
|
436
|
+
old_buffer.active = was_active if old_buffer
|
437
|
+
@haml_buffer = old_buffer
|
438
|
+
end
|
439
|
+
|
440
|
+
# Gets a reference to the current Haml::Buffer object.
|
441
|
+
def haml_buffer
|
442
|
+
@haml_buffer
|
443
|
+
end
|
444
|
+
|
445
|
+
# Gives a proc the same local "_hamlout" and "_erbout" variables
|
446
|
+
# that the current template has.
|
447
|
+
def haml_bind_proc(&proc)
|
448
|
+
_hamlout = haml_buffer
|
449
|
+
_erbout = _hamlout.buffer
|
450
|
+
proc { |*args| proc.call(*args) }
|
451
|
+
end
|
452
|
+
|
453
|
+
include ActionViewExtensions if self.const_defined? "ActionViewExtensions"
|
454
|
+
end
|
455
|
+
end
|
456
|
+
|
457
|
+
class Object
|
458
|
+
# Haml overrides various ActionView helpers,
|
459
|
+
# which call an #is_haml? method
|
460
|
+
# to determine whether or not the current context object
|
461
|
+
# is a proper Haml context.
|
462
|
+
# Because ActionView helpers may be included in non-ActionView::Base classes,
|
463
|
+
# it's a good idea to define is_haml? for all objects.
|
464
|
+
def is_haml?
|
465
|
+
false
|
466
|
+
end
|
467
|
+
end
|
468
|
+
|
data/lib/haml/html.rb
ADDED
@@ -0,0 +1,218 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../haml'
|
2
|
+
|
3
|
+
require 'haml/engine'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'hpricot'
|
6
|
+
require 'cgi'
|
7
|
+
|
8
|
+
module Haml
|
9
|
+
# This class contains the functionality used in the +html2haml+ utility,
|
10
|
+
# namely converting HTML documents to Haml templates.
|
11
|
+
# It depends on Hpricot for HTML parsing (http://code.whytheluckystiff.net/hpricot/).
|
12
|
+
class HTML
|
13
|
+
# Creates a new instance of Haml::HTML that will compile the given template,
|
14
|
+
# which can either be a string containing HTML or an Hpricot node,
|
15
|
+
# to a Haml string when +render+ is called.
|
16
|
+
def initialize(template, options = {})
|
17
|
+
@@options = options
|
18
|
+
|
19
|
+
if template.is_a? Hpricot::Node
|
20
|
+
@template = template
|
21
|
+
else
|
22
|
+
if template.is_a? IO
|
23
|
+
template = template.read
|
24
|
+
end
|
25
|
+
|
26
|
+
if @@options[:rhtml]
|
27
|
+
match_to_html(template, /<%=(.*?)-?%>/m, 'loud')
|
28
|
+
match_to_html(template, /<%-?(.*?)-?%>/m, 'silent')
|
29
|
+
end
|
30
|
+
|
31
|
+
method = @@options[:xhtml] ? Hpricot.method(:XML) : method(:Hpricot)
|
32
|
+
@template = method.call(template.gsub('&', '&'))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Processes the document and returns the result as a string
|
37
|
+
# containing the Haml template.
|
38
|
+
def render
|
39
|
+
@template.to_haml(0)
|
40
|
+
end
|
41
|
+
alias_method :to_haml, :render
|
42
|
+
|
43
|
+
module ::Hpricot::Node
|
44
|
+
# Returns the Haml representation of the given node,
|
45
|
+
# at the given tabulation.
|
46
|
+
def to_haml(tabs = 0)
|
47
|
+
parse_text(self.to_s, tabs)
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def tabulate(tabs)
|
53
|
+
' ' * tabs
|
54
|
+
end
|
55
|
+
|
56
|
+
def parse_text(text, tabs)
|
57
|
+
text.strip!
|
58
|
+
if text.empty?
|
59
|
+
String.new
|
60
|
+
else
|
61
|
+
lines = text.split("\n")
|
62
|
+
|
63
|
+
lines.map do |line|
|
64
|
+
line.strip!
|
65
|
+
"#{tabulate(tabs)}#{'\\' if Haml::Engine::SPECIAL_CHARACTERS.include?(line[0])}#{line}\n"
|
66
|
+
end.join
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# :stopdoc:
|
72
|
+
|
73
|
+
def self.options
|
74
|
+
@@options
|
75
|
+
end
|
76
|
+
|
77
|
+
TEXT_REGEXP = /^(\s*).*$/
|
78
|
+
|
79
|
+
class ::Hpricot::Doc
|
80
|
+
def to_haml(tabs = 0)
|
81
|
+
output = ''
|
82
|
+
children.each { |child| output += child.to_haml(0) } if children
|
83
|
+
output
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
class ::Hpricot::XMLDecl
|
88
|
+
def to_haml(tabs = 0)
|
89
|
+
"#{tabulate(tabs)}!!! XML\n"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
class ::Hpricot::DocType
|
94
|
+
def to_haml(tabs = 0)
|
95
|
+
attrs = public_id.scan(/DTD\s+([^\s]+)\s*([^\s]*)\s*([^\s]*)\s*\/\//)[0]
|
96
|
+
if attrs == nil
|
97
|
+
raise Exception.new("Invalid doctype")
|
98
|
+
end
|
99
|
+
|
100
|
+
type, version, strictness = attrs.map { |a| a.downcase }
|
101
|
+
if type == "html"
|
102
|
+
version = "1.0"
|
103
|
+
strictness = "transitional"
|
104
|
+
end
|
105
|
+
|
106
|
+
if version == "1.0" || version.empty?
|
107
|
+
version = nil
|
108
|
+
end
|
109
|
+
|
110
|
+
if strictness == 'transitional' || strictness.empty?
|
111
|
+
strictness = nil
|
112
|
+
end
|
113
|
+
|
114
|
+
version = " #{version}" if version
|
115
|
+
if strictness
|
116
|
+
strictness[0] = strictness[0] - 32
|
117
|
+
strictness = " #{strictness}"
|
118
|
+
end
|
119
|
+
|
120
|
+
"#{tabulate(tabs)}!!!#{version}#{strictness}\n"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
class ::Hpricot::Comment
|
125
|
+
def to_haml(tabs = 0)
|
126
|
+
"#{tabulate(tabs)}/\n#{parse_text(self.content, tabs + 1)}"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
class ::Hpricot::Elem
|
131
|
+
def to_haml(tabs = 0)
|
132
|
+
output = "#{tabulate(tabs)}"
|
133
|
+
if HTML.options[:rhtml] && name[0...5] == 'haml:'
|
134
|
+
return output + HTML.send("haml_tag_#{name[5..-1]}", CGI.unescapeHTML(self.inner_text))
|
135
|
+
end
|
136
|
+
|
137
|
+
output += "%#{name}" unless name == 'div' && (static_id? || static_classname?)
|
138
|
+
|
139
|
+
if attributes
|
140
|
+
if static_id?
|
141
|
+
output += "##{attributes['id']}"
|
142
|
+
remove_attribute('id')
|
143
|
+
end
|
144
|
+
if static_classname?
|
145
|
+
attributes['class'].split(' ').each { |c| output += ".#{c}" }
|
146
|
+
remove_attribute('class')
|
147
|
+
end
|
148
|
+
output += haml_attributes if attributes.length > 0
|
149
|
+
end
|
150
|
+
|
151
|
+
(self.children || []).inject(output + "\n") do |output, child|
|
152
|
+
output + child.to_haml(tabs + 1)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
private
|
157
|
+
|
158
|
+
def dynamic_attributes
|
159
|
+
@dynamic_attributes ||= begin
|
160
|
+
Haml::Util.map_hash(attributes) do |name, value|
|
161
|
+
next if value.empty?
|
162
|
+
full_match = nil
|
163
|
+
ruby_value = value.gsub(%r{<haml:loud>\s*(.+?)\s*</haml:loud>}) do
|
164
|
+
full_match = $`.empty? && $'.empty?
|
165
|
+
full_match ? $1: "\#{#{$1}}"
|
166
|
+
end
|
167
|
+
next if ruby_value == value
|
168
|
+
[name, full_match ? ruby_value : %("#{ruby_value}")]
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def static_attribute?(name)
|
174
|
+
attributes[name] and !dynamic_attribute?(name)
|
175
|
+
end
|
176
|
+
|
177
|
+
def dynamic_attribute?(name)
|
178
|
+
HTML.options[:rhtml] and dynamic_attributes.key?(name)
|
179
|
+
end
|
180
|
+
|
181
|
+
def static_id?
|
182
|
+
static_attribute? 'id'
|
183
|
+
end
|
184
|
+
|
185
|
+
def static_classname?
|
186
|
+
static_attribute? 'class'
|
187
|
+
end
|
188
|
+
|
189
|
+
# Returns a string representation of an attributes hash
|
190
|
+
# that's prettier than that produced by Hash#inspect
|
191
|
+
def haml_attributes
|
192
|
+
attrs = attributes.map do |name, value|
|
193
|
+
value = dynamic_attribute?(name) ? dynamic_attributes[name] : value.inspect
|
194
|
+
name = name.index(/\W/) ? name.inspect : ":#{name}"
|
195
|
+
"#{name} => #{value}"
|
196
|
+
end
|
197
|
+
"{ #{attrs.join(', ')} }"
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def self.haml_tag_loud(text)
|
202
|
+
"= #{text.gsub(/\n\s*/, ' ').strip}\n"
|
203
|
+
end
|
204
|
+
|
205
|
+
def self.haml_tag_silent(text)
|
206
|
+
text.split("\n").map { |line| "- #{line.strip}\n" }.join
|
207
|
+
end
|
208
|
+
|
209
|
+
private
|
210
|
+
|
211
|
+
def match_to_html(string, regex, tag)
|
212
|
+
string.gsub!(regex) do
|
213
|
+
"<haml:#{tag}>#{CGI.escapeHTML($1)}</haml:#{tag}>"
|
214
|
+
end
|
215
|
+
end
|
216
|
+
# :startdoc:
|
217
|
+
end
|
218
|
+
end
|