haml 1.8.0 → 2.0.3

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 (89) hide show
  1. data/FAQ +138 -0
  2. data/MIT-LICENSE +1 -1
  3. data/{README → README.rdoc} +66 -3
  4. data/REVISION +1 -0
  5. data/Rakefile +115 -147
  6. data/VERSION +1 -1
  7. data/bin/css2sass +0 -0
  8. data/bin/haml +2 -1
  9. data/bin/html2haml +0 -0
  10. data/bin/sass +0 -0
  11. data/init.rb +6 -1
  12. data/lib/haml/buffer.rb +122 -64
  13. data/lib/haml/engine.rb +77 -46
  14. data/lib/haml/error.rb +15 -6
  15. data/lib/haml/exec.rb +61 -10
  16. data/lib/haml/filters.rb +229 -74
  17. data/lib/haml/helpers/action_view_extensions.rb +1 -1
  18. data/lib/haml/helpers/action_view_mods.rb +109 -24
  19. data/lib/haml/helpers.rb +137 -76
  20. data/lib/haml/html.rb +8 -8
  21. data/lib/haml/precompiler.rb +280 -153
  22. data/lib/haml/template/patch.rb +10 -3
  23. data/lib/haml/template/plugin.rb +61 -10
  24. data/lib/haml/template.rb +14 -9
  25. data/lib/haml.rb +483 -214
  26. data/lib/sass/constant/color.rb +13 -13
  27. data/lib/sass/constant/literal.rb +8 -7
  28. data/lib/sass/constant/nil.rb +9 -0
  29. data/lib/sass/constant/number.rb +10 -10
  30. data/lib/sass/constant/operation.rb +4 -4
  31. data/lib/sass/constant/string.rb +3 -3
  32. data/lib/sass/constant.rb +46 -77
  33. data/lib/sass/css.rb +130 -56
  34. data/lib/sass/engine.rb +131 -43
  35. data/lib/sass/plugin/merb.rb +48 -12
  36. data/lib/sass/plugin/rails.rb +10 -4
  37. data/lib/sass/plugin.rb +33 -10
  38. data/lib/sass/tree/attr_node.rb +5 -5
  39. data/lib/sass/tree/directive_node.rb +2 -7
  40. data/lib/sass/tree/node.rb +1 -12
  41. data/lib/sass/tree/rule_node.rb +39 -31
  42. data/lib/sass/tree/value_node.rb +1 -1
  43. data/lib/sass.rb +194 -19
  44. data/rails/init.rb +1 -0
  45. data/test/benchmark.rb +67 -80
  46. data/test/haml/engine_test.rb +368 -152
  47. data/test/haml/helper_test.rb +68 -16
  48. data/test/haml/html2haml_test.rb +3 -4
  49. data/test/haml/results/content_for_layout.xhtml +1 -2
  50. data/test/haml/results/eval_suppressed.xhtml +2 -4
  51. data/test/haml/results/filters.xhtml +38 -30
  52. data/test/haml/results/helpers.xhtml +4 -8
  53. data/test/haml/results/just_stuff.xhtml +8 -7
  54. data/test/haml/results/nuke_inner_whitespace.xhtml +40 -0
  55. data/test/haml/results/nuke_outer_whitespace.xhtml +148 -0
  56. data/test/haml/results/original_engine.xhtml +3 -7
  57. data/test/haml/results/partials.xhtml +1 -0
  58. data/test/haml/results/tag_parsing.xhtml +1 -6
  59. data/test/haml/results/very_basic.xhtml +2 -4
  60. data/test/haml/results/whitespace_handling.xhtml +13 -21
  61. data/test/haml/template_test.rb +42 -57
  62. data/test/haml/templates/_partial.haml +1 -0
  63. data/test/haml/templates/filters.haml +39 -21
  64. data/test/haml/templates/helpers.haml +10 -10
  65. data/test/haml/templates/just_stuff.haml +8 -3
  66. data/test/haml/templates/nuke_inner_whitespace.haml +32 -0
  67. data/test/haml/templates/nuke_outer_whitespace.haml +144 -0
  68. data/test/haml/templates/partials.haml +1 -1
  69. data/test/haml/templates/tag_parsing.haml +0 -3
  70. data/test/haml/templates/whitespace_handling.haml +10 -10
  71. data/test/sass/engine_test.rb +97 -39
  72. data/test/sass/plugin_test.rb +4 -7
  73. data/test/sass/results/constants.css +2 -0
  74. data/test/sass/results/import.css +2 -2
  75. data/test/sass/results/mixins.css +95 -0
  76. data/test/sass/results/multiline.css +24 -0
  77. data/test/sass/templates/constants.sass +3 -0
  78. data/test/sass/templates/import.sass +4 -1
  79. data/test/sass/templates/importee.sass +4 -0
  80. data/test/sass/templates/mixins.sass +76 -0
  81. data/test/sass/templates/multiline.sass +20 -0
  82. data/test/test_helper.rb +18 -0
  83. metadata +70 -53
  84. data/lib/haml/helpers/action_view_mods.rb.rej +0 -30
  85. data/lib/haml/util.rb +0 -18
  86. data/lib/sass/constant.rb.rej +0 -42
  87. data/test/haml/runner.rb +0 -16
  88. data/test/profile.rb +0 -65
  89. data/test/sass/engine_test.rb.rej +0 -18
data/lib/haml.rb CHANGED
@@ -2,18 +2,18 @@ dir = File.dirname(__FILE__)
2
2
  $LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
3
3
 
4
4
  # = Haml (XHTML Abstraction Markup Language)
5
- #
5
+ #
6
6
  # Haml is a markup language
7
7
  # that's used to cleanly and simply describe the XHTML of any web document,
8
8
  # without the use of inline code.
9
9
  # Haml functions as a replacement
10
- # for inline page templating systems such as PHP, ERB, and ASP.
11
- # However, Haml avoids the need for explicitly coding XHTML into the template,
10
+ # for inline page templating systems such as PHP, ERB, and ASP.
11
+ # However, Haml avoids the need for explicitly coding XHTML into the template,
12
12
  # because it is actually an abstract description of the XHTML,
13
13
  # with some code to generate dynamic content.
14
- #
14
+ #
15
15
  # == Features
16
- #
16
+ #
17
17
  # * Whitespace active
18
18
  # * Well-formatted markup
19
19
  # * DRY
@@ -23,51 +23,50 @@ $LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
23
23
  #
24
24
  # == Using Haml
25
25
  #
26
- # Haml can be used in two ways:
26
+ # Haml can be used in three ways:
27
27
  # as a plugin for Ruby on Rails,
28
- # and as a standalone Ruby module.
29
- #
30
- # Sass can be used in several ways:
31
- # As a template engine for Ruby on Rails or Merb,
32
- # or as a standalone engine.
28
+ # as a standalone Ruby module,
29
+ # and as a command-line tool.
33
30
  # The first step for all of these is to install the Haml gem:
34
31
  #
35
32
  # gem install haml
36
33
  #
37
34
  # To enable it as a Rails plugin,
38
35
  # then run
39
- #
36
+ #
40
37
  # haml --rails path/to/rails/app
41
- #
42
- # Haml is enabled in Merb by default,
43
- # so Merb users don't have to do anything more.
44
38
  #
45
- # Once it's installed, all view files with the ".haml" extension
46
- # (or ".html.haml" for Merb or edge Rails)
39
+ # Once it's installed, all view files with the ".html.haml" extension
47
40
  # will be compiled using Haml.
48
41
  #
42
+ # To run Haml from the commandline, just use
43
+ #
44
+ # haml input.haml output.html
45
+ #
46
+ # Use <tt>haml --help</tt> for full documentation.
47
+ #
49
48
  # You can access instance variables in Haml templates
50
49
  # the same way you do in ERb templates.
51
50
  # Helper methods are also available in Haml templates.
52
51
  # For example (this example uses Rails, but the principle for Merb is the same):
53
- #
52
+ #
54
53
  # # file: app/controllers/movies_controller.rb
55
- #
54
+ #
56
55
  # class MoviesController < ApplicationController
57
56
  # def index
58
57
  # @title = "Teen Wolf"
59
58
  # end
60
59
  # end
61
- #
60
+ #
62
61
  # -# file: app/views/movies/index.haml
63
- #
62
+ #
64
63
  # #content
65
64
  # .title
66
65
  # %h1= @title
67
66
  # = link_to 'Home', home_url
68
- #
67
+ #
69
68
  # may be compiled to:
70
- #
69
+ #
71
70
  # <div id='content'>
72
71
  # <div class='title'>
73
72
  # <h1>Teen Wolf</h1>
@@ -89,41 +88,41 @@ $LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
89
88
  # engine.render #=> "<p>Haml code!</p>\n"
90
89
  #
91
90
  # == Characters with meaning to Haml
92
- #
91
+ #
93
92
  # Various characters, when placed at a certain point in a line,
94
93
  # instruct Haml to render different types of things.
95
- #
94
+ #
96
95
  # === XHTML Tags
97
- #
96
+ #
98
97
  # These characters render XHTML tags.
99
- #
98
+ #
100
99
  # ==== %
101
- #
102
- #
100
+ #
101
+ #
103
102
  # The percent character is placed at the beginning of a line.
104
103
  # It's followed immediately by the name of an element,
105
104
  # then optionally by modifiers (see below), a space,
106
105
  # and text to be rendered inside the element.
107
106
  # It creates an element in the form of <tt><element></element></tt>.
108
107
  # For example:
109
- #
108
+ #
110
109
  # %one
111
110
  # %two
112
111
  # %three Hey there
113
- #
112
+ #
114
113
  # is compiled to:
115
- #
114
+ #
116
115
  # <one>
117
116
  # <two>
118
117
  # <three>Hey there</three>
119
118
  # </two>
120
119
  # </one>
121
- #
120
+ #
122
121
  # Any string is a valid element name;
123
122
  # Haml will automatically generate opening and closing tags for any element.
124
- #
123
+ #
125
124
  # ==== {}
126
- #
125
+ #
127
126
  # Brackets represent a Ruby hash
128
127
  # that is used for specifying the attributes of an element.
129
128
  # It is literally evaluated as a Ruby hash,
@@ -132,18 +131,20 @@ $LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
132
131
  # will be replaced by appropriate escape sequences.
133
132
  # The hash is placed after the tag is defined.
134
133
  # For example:
135
- #
134
+ #
136
135
  # %head{ :name => "doc_head" }
137
136
  # %script{ 'type' => "text/" + "javascript",
138
137
  # :src => "javascripts/script_#{2 + 7}" }
139
- #
138
+ #
140
139
  # is compiled to:
141
- #
140
+ #
142
141
  # <head name="doc_head">
143
142
  # <script src='javascripts/script_9' type='text/javascript'>
144
143
  # </script>
145
144
  # </head>
146
145
  #
146
+ # ===== Attribute Methods
147
+ #
147
148
  # A Ruby method call that returns a hash
148
149
  # can be substituted for the hash contents.
149
150
  # For example, Haml::Helpers defines the following method:
@@ -182,9 +183,36 @@ $LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
182
183
  # would compile to:
183
184
  #
184
185
  # <sandwich bread='whole wheat' delicious='true' filling='peanut butter and jelly' />
185
- #
186
+ #
187
+ # ===== Boolean Attributes
188
+ #
189
+ # Some attributes, such as "checked" for <tt>input</tt> tags or "selected" for <tt>option</tt> tags,
190
+ # are "boolean" in the sense that their values don't matter -
191
+ # it only matters whether or not they're present.
192
+ # In HTML (but not XHTML), these attributes can be written as
193
+ #
194
+ # <input selected>
195
+ #
196
+ # To do this in Haml, just assign a Ruby true value to the attribute:
197
+ #
198
+ # %input{:selected => true}
199
+ #
200
+ # In XHTML, the only valid value for these attributes is the name of the attribute.
201
+ # Thus this will render in XHTML as
202
+ #
203
+ # <input selected="selected">
204
+ #
205
+ # To set these attributes to false, simply assign them to a Ruby false value.
206
+ # In both XHTML and HTML
207
+ #
208
+ # %input{:selected => false}
209
+ #
210
+ # will just render as
211
+ #
212
+ # <input>
213
+ #
186
214
  # ==== []
187
- #
215
+ #
188
216
  # Square brackets follow a tag definition and contain a Ruby object
189
217
  # that is used to set the class and id of that tag.
190
218
  # The class is set to the object's class
@@ -192,41 +220,40 @@ $LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
192
220
  # and the id is set to the object's class, followed by its id.
193
221
  # Because the id of an object is normally an obscure implementation detail,
194
222
  # this is most useful for elements that represent instances of Models.
223
+ # Additionally, the second argument (if present) will be used as a prefix for
224
+ # both the id and class attributes.
195
225
  # For example:
196
- #
226
+ #
197
227
  # # file: app/controllers/users_controller.rb
198
- #
228
+ #
199
229
  # def show
200
230
  # @user = CrazyUser.find(15)
201
231
  # end
202
- #
232
+ #
203
233
  # -# file: app/views/users/show.haml
204
- #
205
- # %div[@user]
234
+ #
235
+ # %div[@user, :greeting]
206
236
  # %bar[290]/
207
237
  # Hello!
208
- #
238
+ #
209
239
  # is compiled to:
210
- #
211
- # <div class="crazy_user" id="crazy_user_15">
240
+ #
241
+ # <div class="greeting_crazy_user" id="greeting_crazy_user_15">
212
242
  # <bar class="fixnum" id="fixnum_581" />
213
243
  # Hello!
214
244
  # </div>
215
- #
216
- # This is based off of DHH's SimplyHelpful syntax,
217
- # as presented at RailsConf Europe 2006.
218
- #
245
+ #
219
246
  # ==== /
220
- #
247
+ #
221
248
  # The forward slash character, when placed at the end of a tag definition,
222
249
  # causes the tag to be self-closed.
223
250
  # For example:
224
- #
251
+ #
225
252
  # %br/
226
253
  # %meta{'http-equiv' => 'Content-Type', :content => 'text/html'}/
227
- #
254
+ #
228
255
  # is compiled to:
229
- #
256
+ #
230
257
  # <br />
231
258
  # <meta http-equiv='Content-Type' content='text/html' />
232
259
  #
@@ -242,9 +269,9 @@ $LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
242
269
  #
243
270
  # <br />
244
271
  # <meta http-equiv='Content-Type' content='text/html' />
245
- #
272
+ #
246
273
  # ==== . and #
247
- #
274
+ #
248
275
  # The period and pound sign are borrowed from CSS.
249
276
  # They are used as shortcuts to specify the <tt>class</tt>
250
277
  # and <tt>id</tt> attributes of an element, respectively.
@@ -252,22 +279,22 @@ $LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
252
279
  # by chaining the class names together with periods.
253
280
  # They are placed immediately after the tag and before an attributes hash.
254
281
  # For example:
255
- #
282
+ #
256
283
  # %div#things
257
284
  # %span#rice Chicken Fried
258
285
  # %p.beans{ :food => 'true' } The magical fruit
259
286
  # %h1.class.otherclass#id La La La
260
- #
287
+ #
261
288
  # is compiled to:
262
- #
289
+ #
263
290
  # <div id='things'>
264
291
  # <span id='rice'>Chicken Fried</span>
265
292
  # <p class='beans' food='true'>The magical fruit</p>
266
293
  # <h1 class='class otherclass' id='id'>La La La</h1>
267
294
  # </div>
268
- #
295
+ #
269
296
  # And,
270
- #
297
+ #
271
298
  # #content
272
299
  # .articles
273
300
  # .article.title
@@ -276,9 +303,9 @@ $LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
276
303
  # 2006-11-05
277
304
  # .article.entry
278
305
  # Neil Patrick Harris would like to dispel any rumors that he is straight
279
- #
306
+ #
280
307
  # is compiled to:
281
- #
308
+ #
282
309
  # <div id="content">
283
310
  # <div class="articles">
284
311
  # <div class="article title">Doogie Howser Comes Out</div>
@@ -288,34 +315,89 @@ $LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
288
315
  # </div>
289
316
  # </div>
290
317
  # </div>
291
- #
318
+ #
292
319
  # ==== Implicit Div Elements
293
- #
320
+ #
294
321
  # Because the div element is used so often, it is the default element.
295
322
  # If you only define a class and/or id using the <tt>.</tt> or <tt>#</tt> syntax,
296
323
  # a div element is automatically used.
297
324
  # For example:
298
- #
325
+ #
299
326
  # #collection
300
327
  # .item
301
328
  # .description What a cool item!
302
- #
329
+ #
303
330
  # is the same as:
304
- #
331
+ #
305
332
  # %div{:id => collection}
306
333
  # %div{:class => 'item'}
307
334
  # %div{:class => 'description'} What a cool item!
308
- #
335
+ #
309
336
  # and is compiled to:
310
- #
337
+ #
311
338
  # <div id='collection'>
312
339
  # <div class='item'>
313
340
  # <div class='description'>What a cool item!</div>
314
341
  # </div>
315
342
  # </div>
316
- #
343
+ #
344
+ # ==== > and <
345
+ #
346
+ # <tt>></tt> and <tt><</tt> give you more control over the whitespace near a tag.
347
+ # <tt>></tt> will remove all whitespace surrounding a tag,
348
+ # while <tt><</tt> will remove all whitespace immediately within a tag.
349
+ # You can think of them as alligators eating the whitespace:
350
+ # <tt>></tt> faces out of the tag and eats the whitespace on the outside,
351
+ # and <tt><</tt> faces into the tag and eats the whitespace on the inside.
352
+ # They're placed at the end of a tag definition,
353
+ # after class, id, and attribute declarations
354
+ # but before <tt>/</tt> or <tt>=</tt>.
355
+ # For example:
356
+ #
357
+ # %blockquote<
358
+ # %div
359
+ # Foo!
360
+ #
361
+ # is compiled to:
362
+ #
363
+ # <blockquote><div>
364
+ # Foo!
365
+ # </div></blockquote>
366
+ #
367
+ # And:
368
+ #
369
+ # %img
370
+ # %img>
371
+ # %img
372
+ #
373
+ # is compiled to:
374
+ #
375
+ # <img /><img /><img />
376
+ #
377
+ # And:
378
+ #
379
+ # %p<= "Foo\nBar"
380
+ #
381
+ # is compiled to:
382
+ #
383
+ # <p>Foo
384
+ # Bar</p>
385
+ #
386
+ # And finally:
387
+ #
388
+ # %img
389
+ # %pre><
390
+ # foo
391
+ # bar
392
+ # %img
393
+ #
394
+ # is compiled to:
395
+ #
396
+ # <img /><pre>foo
397
+ # bar</pre><img />
398
+ #
317
399
  # ==== =
318
- #
400
+ #
319
401
  # <tt>=</tt> is placed at the end of a tag definition,
320
402
  # after class, id, and attribute declarations.
321
403
  # It's just a shortcut for inserting Ruby code into an element.
@@ -324,45 +406,63 @@ $LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
324
406
  # However, if the result is short enough,
325
407
  # it is displayed entirely on one line.
326
408
  # For example:
327
- #
409
+ #
328
410
  # %p= "hello"
329
- #
411
+ #
330
412
  # is not quite the same as:
331
- #
413
+ #
332
414
  # %p
333
415
  # = "hello"
334
- #
416
+ #
335
417
  # It's compiled to:
336
- #
418
+ #
337
419
  # <p>hello</p>
338
- #
420
+ #
421
+ # ==== ~
422
+ #
423
+ # ~ works just like =, except that it runs Haml::Helpers#find_and_preserve on its input.
424
+ # For example,
425
+ #
426
+ # ~ "Foo\n<pre>Bar\nBaz</pre>"
427
+ #
428
+ # is the same as:
429
+ #
430
+ # = find_and_preserve("Foo\n<pre>Bar\nBaz</pre>")
431
+ #
432
+ # and is compiled to:
433
+ #
434
+ # Foo
435
+ # <pre>Bar&#x000A;Baz</pre>
436
+ #
437
+ # See also Whitespace Preservation, below.
438
+ #
339
439
  # === XHTML Helpers
340
- #
440
+ #
341
441
  # ==== No Special Character
342
- #
442
+ #
343
443
  # If no special character appears at the beginning of a line,
344
444
  # the line is rendered as plain text.
345
445
  # For example:
346
- #
446
+ #
347
447
  # %gee
348
448
  # %whiz
349
449
  # Wow this is cool!
350
- #
450
+ #
351
451
  # is compiled to:
352
- #
452
+ #
353
453
  # <gee>
354
454
  # <whiz>
355
455
  # Wow this is cool!
356
456
  # </whiz>
357
457
  # </gee>
358
- #
458
+ #
359
459
  # ==== !!!
360
- #
460
+ #
361
461
  # When describing XHTML documents with Haml,
362
462
  # you can have a document type or XML prolog generated automatically
363
463
  # by including the characters <tt>!!!</tt>.
364
464
  # For example:
365
- #
465
+ #
366
466
  # !!! XML
367
467
  # !!!
368
468
  # %html
@@ -371,9 +471,9 @@ $LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
371
471
  # %body
372
472
  # %h1 I am the international space station
373
473
  # %p Sign my guestbook
374
- #
474
+ #
375
475
  # is compiled to:
376
- #
476
+ #
377
477
  # <?xml version="1.0" encoding="utf-8" ?>
378
478
  # <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
379
479
  # <html>
@@ -385,112 +485,112 @@ $LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
385
485
  # <p>Sign my guestbook</p>
386
486
  # </body>
387
487
  # </html>
388
- #
488
+ #
389
489
  # You can also specify the version and type of XHTML after the <tt>!!!</tt>.
390
490
  # XHTML 1.0 Strict, Transitional, and Frameset and XHTML 1.1 are supported.
391
491
  # The default version is 1.0 and the default type is Transitional.
392
492
  # For example:
393
- #
493
+ #
394
494
  # !!! 1.1
395
- #
495
+ #
396
496
  # is compiled to:
397
- #
497
+ #
398
498
  # <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
399
- #
499
+ #
400
500
  # and
401
- #
501
+ #
402
502
  # !!! Strict
403
- #
503
+ #
404
504
  # is compiled to:
405
- #
505
+ #
406
506
  # <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
407
- #
507
+ #
408
508
  # If you're not using the UTF-8 character set for your document,
409
509
  # you can specify which encoding should appear
410
510
  # in the XML prolog in a similar way.
411
511
  # For example:
412
- #
512
+ #
413
513
  # !!! XML iso-8859-1
414
- #
514
+ #
415
515
  # is compiled to:
416
- #
516
+ #
417
517
  # <?xml version="1.0" encoding="iso-8859-1" ?>
418
- #
518
+ #
419
519
  # ==== /
420
- #
520
+ #
421
521
  # The forward slash character, when placed at the beginning of a line,
422
522
  # wraps all text after it in an HTML comment.
423
523
  # For example:
424
- #
524
+ #
425
525
  # %peanutbutterjelly
426
526
  # / This is the peanutbutterjelly element
427
527
  # I like sandwiches!
428
- #
528
+ #
429
529
  # is compiled to:
430
- #
530
+ #
431
531
  # <peanutbutterjelly>
432
532
  # <!-- This is the peanutbutterjelly element -->
433
533
  # I like sandwiches!
434
534
  # </peanutbutterjelly>
435
- #
535
+ #
436
536
  # The forward slash can also wrap indented sections of code. For example:
437
- #
537
+ #
438
538
  # /
439
539
  # %p This doesn't render...
440
540
  # %div
441
541
  # %h1 Because it's commented out!
442
- #
542
+ #
443
543
  # is compiled to:
444
- #
544
+ #
445
545
  # <!--
446
546
  # <p>This doesn't render...</p>
447
547
  # <div>
448
548
  # <h1>Because it's commented out!</h1>
449
549
  # </div>
450
550
  # -->
451
- #
551
+ #
452
552
  # You can also use Internet Explorer conditional comments
453
553
  # (about)[http://www.quirksmode.org/css/condcom.html]
454
554
  # by enclosing the condition in square brackets after the <tt>/</tt>.
455
555
  # For example:
456
- #
556
+ #
457
557
  # /[if IE]
458
558
  # %a{ :href => 'http://www.mozilla.com/en-US/firefox/' }
459
559
  # %h1 Get Firefox
460
- #
560
+ #
461
561
  # is compiled to:
462
- #
562
+ #
463
563
  # <!--[if IE]>
464
564
  # <a href='http://www.mozilla.com/en-US/firefox/'>
465
565
  # <h1>Get Firefox</h1>
466
566
  # </a>
467
567
  # <![endif]-->
468
- #
568
+ #
469
569
  # ==== \
470
- #
570
+ #
471
571
  # The backslash character escapes the first character of a line,
472
572
  # allowing use of otherwise interpreted characters as plain text.
473
573
  # For example:
474
- #
574
+ #
475
575
  # %title
476
576
  # = @title
477
577
  # \- MySite
478
- #
578
+ #
479
579
  # is compiled to:
480
- #
580
+ #
481
581
  # <title>
482
582
  # MyPage
483
583
  # - MySite
484
584
  # </title>
485
- #
585
+ #
486
586
  # ==== |
487
- #
587
+ #
488
588
  # The pipe character designates a multiline string.
489
589
  # It's placed at the end of a line
490
590
  # and means that all following lines that end with <tt>|</tt>
491
591
  # will be evaluated as though they were on the same line.
492
592
  # For example:
493
- #
593
+ #
494
594
  # %whoo
495
595
  # %hoo I think this might get |
496
596
  # pretty long so I should |
@@ -498,13 +598,14 @@ $LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
498
598
  # multiline so it doesn't |
499
599
  # look awful. |
500
600
  # %p This is short.
501
- #
601
+ #
502
602
  # is compiled to:
503
- #
603
+ #
504
604
  # <whoo>
505
605
  # <hoo>
506
606
  # I think this might get pretty long so I should probably make it multiline so it doesn't look awful.
507
607
  # </hoo>
608
+ # <p>This is short</p>
508
609
  # </whoo>
509
610
  #
510
611
  # ==== :
@@ -530,101 +631,176 @@ $LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
530
631
  # <p>Hello, <em>World</em></p>
531
632
  # </p>
532
633
  #
634
+ # Filters can have Ruby code interpolated, like with ==.
635
+ # For example,
636
+ #
637
+ # - flavor = "raspberry"
638
+ # #content
639
+ # :textile
640
+ # I *really* prefer _#{h flavor}_ jam.
641
+ #
642
+ # is compiled to
643
+ #
644
+ # <div id='content'>
645
+ # <p>I <strong>really</strong> prefer <em>raspberry</em> jam.</p>
646
+ # </div>
647
+ #
533
648
  # Haml has the following filters defined:
534
649
  #
535
- # [plain] Does not parse the filtered text.
536
- # This is useful for large blocks of text without HTML tags,
537
- # when you don't want lines starting with <tt>.</tt> or <tt>-</tt>
538
- # to be parsed.
650
+ # [plain] Does not parse the filtered text.
651
+ # This is useful for large blocks of text without HTML tags,
652
+ # when you don't want lines starting with <tt>.</tt> or <tt>-</tt>
653
+ # to be parsed.
539
654
  #
540
- # [ruby] Parses the filtered text with the normal Ruby interpreter.
541
- # All output sent to <tt>$stdout</tt>, like with +puts+,
542
- # is output into the Haml document.
543
- # Not available if the <tt>suppress_eval</tt> option is set to true.
655
+ # [javascript] Surrounds the filtered text with <script> and CDATA tags.
656
+ # Useful for including inline Javascript.
544
657
  #
545
- # [preserve] Inserts the filtered text into the template with whitespace preserved.
546
- # <tt>preserve</tt>d blocks of text aren't indented,
547
- # and newlines are replaced with the HTML escape code for newlines,
548
- # to preserve nice-looking output.
658
+ # [escaped] Works the same as plain, but HTML-escapes the text
659
+ # before placing it in the document.
549
660
  #
550
- # [erb] Parses the filtered text with ERB, like an RHTML template.
551
- # Not available if the <tt>suppress_eval</tt> option is set to true.
552
- # At the moment, this doesn't support access to variables
553
- # defined by Ruby on Rails or Haml code.
661
+ # [ruby] Parses the filtered text with the normal Ruby interpreter.
662
+ # All output sent to <tt>$stdout</tt>, like with +puts+,
663
+ # is output into the Haml document.
664
+ # Not available if the <tt>suppress_eval</tt> option is set to true.
665
+ # The Ruby code is evaluated in the same context as the Haml template.
554
666
  #
555
- # [sass] Parses the filtered text with Sass to produce CSS output.
667
+ # [preserve] Inserts the filtered text into the template with whitespace preserved.
668
+ # <tt>preserve</tt>d blocks of text aren't indented,
669
+ # and newlines are replaced with the HTML escape code for newlines,
670
+ # to preserve nice-looking output.
671
+ # See also Whitespace Preservation, below.
556
672
  #
557
- # [redcloth] Parses the filtered text with RedCloth (http://whytheluckystiff.net/ruby/redcloth),
558
- # which uses both Textile and Markdown syntax.
559
- # Only works if RedCloth is installed.
673
+ # [erb] Parses the filtered text with ERB, like an RHTML template.
674
+ # Not available if the <tt>suppress_eval</tt> option is set to true.
675
+ # Embedded Ruby code is evaluated in the same context as the Haml template.
560
676
  #
561
- # [textile] Parses the filtered text with Textile (http://www.textism.com/tools/textile).
562
- # Only works if RedCloth is installed.
677
+ # [sass] Parses the filtered text with Sass to produce CSS output.
563
678
  #
564
- # [markdown] Parses the filtered text with Markdown (http://daringfireball.net/projects/markdown).
565
- # Only works if RedCloth or BlueCloth (http://www.deveiate.org/projects/BlueCloth)
566
- # is installed
567
- # (BlueCloth takes precedence if both are installed).
679
+ # [textile] Parses the filtered text with Textile (http://www.textism.com/tools/textile).
680
+ # Only works if RedCloth is installed.
681
+ #
682
+ # [markdown] Parses the filtered text with Markdown (http://daringfireball.net/projects/markdown).
683
+ # Only works if RDiscount, RPeg-Markdown, Maruku, or BlueCloth are installed.
684
+ #
685
+ # [maruku] Parses the filtered text with Maruku, which has some non-standard extensions to Markdown.
686
+ #
687
+ # You can also define your own filters (see Haml::Filters).
568
688
  #
569
- # You can also define your own filters (see Setting Options, below).
570
- #
571
689
  # === Ruby evaluators
572
- #
690
+ #
573
691
  # ==== =
574
- #
692
+ #
575
693
  # The equals character is followed by Ruby code,
576
694
  # which is evaluated and the output inserted into the document as plain text.
577
695
  # For example:
578
- #
696
+ #
579
697
  # %p
580
698
  # = ['hi', 'there', 'reader!'].join " "
581
699
  # = "yo"
582
- #
700
+ #
583
701
  # is compiled to:
584
- #
702
+ #
585
703
  # <p>
586
704
  # hi there reader!
587
705
  # yo
588
706
  # </p>
589
707
  #
590
- # You can also use two equal signs, <tt>==</tt>,
591
- # along with conventional Ruby string-embedding syntax
592
- # to easily embed Ruby code in otherwise static text.
593
- # For example:
708
+ # If the <tt>:escape_html</tt> option is set, <tt>=</tt> will sanitize any
709
+ # HTML-sensitive characters generated by the script. For example:
594
710
  #
595
- # %p
596
- # == 1 + 1 = #{1 + 1}
711
+ # = '<script>alert("I\'m evil!");</script>'
597
712
  #
598
- # is compiled to:
713
+ # would be compiled to
714
+ #
715
+ # &lt;script&gt;alert(&quot;I'm evil!&quot;);&lt;/script&gt;
599
716
  #
600
- # <p>
601
- # 1 + 1 = 2
602
- # </p>
603
- #
604
717
  # ==== -
605
- #
718
+ #
606
719
  # The hyphen character makes the text following it into "silent script":
607
720
  # Ruby script that is evaluated, but not output.
608
- #
721
+ #
609
722
  # <b>It is not recommended that you use this widely;
610
723
  # almost all processing code and logic should be restricted
611
724
  # to the Controller, the Helper, or partials.</b>
612
- #
725
+ #
613
726
  # For example:
614
- #
727
+ #
615
728
  # - foo = "hello"
616
729
  # - foo << " there"
617
730
  # - foo << " you!"
618
731
  # %p= foo
619
- #
732
+ #
620
733
  # is compiled to:
621
- #
734
+ #
622
735
  # <p>
623
736
  # hello there you!
624
737
  # </p>
625
- #
738
+ #
739
+ # ==== ==
740
+ #
741
+ # Two equals characters interpolates Ruby code into plain text,
742
+ # similarly to Ruby string interpolation.
743
+ # For example,
744
+ #
745
+ # %p== This is #{h quality} cake!
746
+ #
747
+ # is the same as
748
+ #
749
+ # %p= "This is #{h quality} cake!"
750
+ #
751
+ # and might compile to
752
+ #
753
+ # <p>This is scrumptious cake!</p>
754
+ #
755
+ # Backslashes can be used to escape "#{" strings,
756
+ # but they don't act as escapes anywhere else in the string.
757
+ # For example:
758
+ #
759
+ # %p
760
+ # == \\ Look at \\#{h word} lack of backslash: \#{foo}
761
+ #
762
+ # might compile to
763
+ #
764
+ # <p>
765
+ # \\ Look at \yon lack of backslash: #{foo}
766
+ # </p>
767
+ #
768
+ # ==== &=
769
+ #
770
+ # An ampersand followed by one or two equals characters
771
+ # evaluates Ruby code just like the equals without the ampersand,
772
+ # but sanitizes any HTML-sensitive characters in the result of the code.
773
+ # For example:
774
+ #
775
+ # &= "I like cheese & crackers"
776
+ #
777
+ # compiles to
778
+ #
779
+ # I like cheese &amp; crackers
780
+ #
781
+ # If the <tt>:escape_html</tt> option is set,
782
+ # &= behaves identically to =.
783
+ #
784
+ # ==== !=
785
+ #
786
+ # An exclamation mark followed by one or two equals characters
787
+ # evaluates Ruby code just like the equals would,
788
+ # but never sanitizes the HTML.
789
+ #
790
+ # By default, the single equals doesn't sanitize HTML either.
791
+ # However, if the <tt>:escape_html</tt> option is set, = will sanitize the HTML, but != still won't.
792
+ # For example, if <tt>:escape_html</tt> is set:
793
+ #
794
+ # = "I feel <strong>!"
795
+ # != "I feel <strong>!"
796
+ #
797
+ # compiles to
798
+ #
799
+ # I feel &lt;strong&gt;!
800
+ # I feel <strong>!
801
+ #
626
802
  # ===== Blocks
627
- #
803
+ #
628
804
  # Ruby blocks, like XHTML tags, don't need to be explicitly closed in Haml.
629
805
  # Rather, they're automatically closed, based on indentation.
630
806
  # A block begins whenever the indentation is increased
@@ -632,13 +808,13 @@ $LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
632
808
  # It ends when the indentation decreases
633
809
  # (as long as it's not an +else+ clause or something similar).
634
810
  # For example:
635
- #
811
+ #
636
812
  # - (42...47).each do |i|
637
813
  # %p= i
638
814
  # %p See, I can count!
639
- #
815
+ #
640
816
  # is compiled to:
641
- #
817
+ #
642
818
  # <p>
643
819
  # 42
644
820
  # </p>
@@ -654,9 +830,9 @@ $LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
654
830
  # <p>
655
831
  # 46
656
832
  # </p>
657
- #
833
+ #
658
834
  # Another example:
659
- #
835
+ #
660
836
  # %p
661
837
  # - case 2
662
838
  # - when 1
@@ -665,9 +841,9 @@ $LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
665
841
  # = "2?"
666
842
  # - when 3
667
843
  # = "3."
668
- #
844
+ #
669
845
  # is compiled to:
670
- #
846
+ #
671
847
  # <p>
672
848
  # 2?
673
849
  # </p>
@@ -678,35 +854,52 @@ $LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
678
854
  # signifies a silent comment.
679
855
  # Any text following this isn't rendered in the resulting document
680
856
  # at all.
681
- #
857
+ #
682
858
  # For example:
683
859
  #
684
- # %p foo
685
- # -# This is a comment
686
- # %p bar
860
+ # %p foo
861
+ # -# This is a comment
862
+ # %p bar
687
863
  #
688
864
  # is compiled to:
689
865
  #
690
- # <p>foo</p>
691
- # <p>bar</p>
866
+ # <p>foo</p>
867
+ # <p>bar</p>
692
868
  #
693
869
  # You can also nest text beneath a silent comment.
694
870
  # None of this text will be rendered.
695
871
  # For example:
696
872
  #
697
- # %p foo
698
- # -#
699
- # This won't be displayed
700
- # Nor will this
701
- # %p bar
873
+ # %p foo
874
+ # -#
875
+ # This won't be displayed
876
+ # Nor will this
877
+ # %p bar
702
878
  #
703
879
  # is compiled to:
704
880
  #
705
- # <p>foo</p>
706
- # <p>bar</p>
707
- #
881
+ # <p>foo</p>
882
+ # <p>bar</p>
883
+ #
708
884
  # == Other Useful Things
709
885
  #
886
+ # === Whitespace Preservation
887
+ #
888
+ # Sometimes you don't want Haml to indent all your text.
889
+ # For example, tags like +pre+ and +textarea+ are whitespace-sensitive;
890
+ # indenting the text makes them render wrong.
891
+ #
892
+ # Haml deals with this by "preserving" newlines before they're put into the document --
893
+ # converting them to the XHTML whitespace escape code, <tt>&#x000A;</tt>.
894
+ # Then Haml won't try to re-format the indentation.
895
+ #
896
+ # Literal +textarea+ and +pre+ tags automatically preserve their content.
897
+ # Dynamically can't be caught automatically,
898
+ # and so should be passed through Haml::Helpers#find_and_preserve or the <tt>~</tt> command,
899
+ # which has the same effect (see above).
900
+ #
901
+ # Blocks of literal text can be preserved using the :preserve filter (see above).
902
+ #
710
903
  # === Helpers
711
904
  #
712
905
  # Haml offers a bunch of helpers that are useful
@@ -714,19 +907,38 @@ $LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
714
907
  # creating nicely indented output for user-defined helpers,
715
908
  # and other useful things.
716
909
  # The helpers are all documented in the Haml::Helpers and Haml::Helpers::ActionViewExtensions modules.
717
- #
910
+ #
718
911
  # === Haml Options
912
+ #
913
+ # Options can be set by setting the <tt>Haml::Template.options</tt> hash
914
+ # in <tt>environment.rb</tt> in Rails...
915
+ #
916
+ # Haml::Template.options[:format] = :html5
917
+ #
918
+ # ...or by setting the <tt>Merb::Config[:haml]</tt> hash in <tt>init.rb</tt> in Merb...
919
+ #
920
+ # Merb::Config[:haml][:format] = :html5
719
921
  #
720
- # Options can be set by setting the hash <tt>Haml::Template.options</tt>
721
- # from <tt>environment.rb</tt> in Rails,
722
- # or by passing an options hash to Haml::Engine.
922
+ # ...or by passing an options hash to Haml::Engine.new.
723
923
  # Available options are:
724
- #
924
+ #
925
+ # [<tt>:format</tt>] Determines the output format. The default is :xhtml.
926
+ # Other options are :html4 and :html5, which are
927
+ # identical to :xhtml except there are no self-closing tags,
928
+ # XML prolog is ignored and correct DOCTYPEs are generated.
929
+ #
930
+ # [<tt>:escape_html</tt>] Sets whether or not to escape HTML-sensitive characters in script.
931
+ # If this is true, = behaves like &=;
932
+ # otherwise, it behaves like !=.
933
+ # Note that if this is set, != should be used for yielding to subtemplates
934
+ # and rendering partials.
935
+ # Defaults to false.
936
+ #
725
937
  # [<tt>:suppress_eval</tt>] Whether or not attribute hashes and Ruby scripts
726
938
  # designated by <tt>=</tt> or <tt>~</tt> should be
727
939
  # evaluated. If this is true, said scripts are
728
940
  # rendered as empty strings. Defaults to false.
729
- #
941
+ #
730
942
  # [<tt>:attr_wrapper</tt>] The character that should wrap element attributes.
731
943
  # This defaults to <tt>'</tt> (an apostrophe). Characters
732
944
  # of this type within the attributes will be escaped
@@ -739,27 +951,84 @@ $LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
739
951
  # so it's really only useful for the user to assign
740
952
  # when dealing with Haml programatically.
741
953
  #
742
- # [<tt>:filters</tt>] A hash of filters that can be applied to Haml code.
743
- # The keys are the string names of the filters;
744
- # the values are references to the classes of the filters.
745
- # User-defined filters should always have lowercase keys,
746
- # and should have:
747
- # * An +initialize+ method that accepts one parameter,
748
- # the text to be filtered.
749
- # * A +render+ method that returns the result of the filtering.
954
+ # [<tt>:line</tt>] The line offset of the Haml template being parsed.
955
+ # This is useful for inline templates,
956
+ # similar to the last argument to Kernel#eval.
750
957
  #
751
958
  # [<tt>:autoclose</tt>] A list of tag names that should be automatically self-closed
752
959
  # if they have no content.
753
- # Defaults to <tt>['meta', 'img', 'link', 'script', 'br', 'hr']</tt>.
960
+ # Defaults to <tt>['meta', 'img', 'link', 'br', 'hr', 'input', 'area', 'param', 'col', 'base']</tt>.
961
+ #
962
+ # [<tt>:preserve</tt>] A list of tag names that should automatically have their newlines preserved
963
+ # using the Haml::Helpers#preserve helper.
964
+ # This means that any content given on the same line as the tag will be preserved.
965
+ # For example:
966
+ #
967
+ # %textarea= "Foo\nBar"
968
+ #
969
+ # compiles to:
970
+ #
971
+ # <textarea>Foo&&#x000A;Bar</textarea>
972
+ #
973
+ # Defaults to <tt>['textarea', 'pre']</tt>.
974
+ #
975
+ # See also Whitespace Preservation, above.
754
976
  #
755
977
  module Haml
978
+ # Returns a hash representing the version of Haml.
979
+ # The :major, :minor, and :teeny keys have their respective numbers.
980
+ # The :string key contains a human-readable string representation of the version.
981
+ # If Haml is checked out from Git,
982
+ # the :rev key will have the revision hash.
983
+ def self.version
984
+ return @@version if defined?(@@version)
985
+
986
+ numbers = File.read(scope('VERSION')).strip.split('.').map { |n| n.to_i }
987
+ @@version = {
988
+ :major => numbers[0],
989
+ :minor => numbers[1],
990
+ :teeny => numbers[2]
991
+ }
992
+ @@version[:string] = [:major, :minor, :teeny].map { |comp| @@version[comp] }.compact.join('.')
993
+
994
+ if File.exists?(scope('REVISION'))
995
+ rev = File.read(scope('REVISION')).strip
996
+ rev = nil if rev !~ /[a-f0-9]+/
997
+ end
998
+
999
+ if rev.nil? && File.exists?(scope('.git/HEAD'))
1000
+ rev = File.read(scope('.git/HEAD')).strip
1001
+ if rev =~ /^ref: (.*)$/
1002
+ rev = File.read(scope(".git/#{$1}")).strip
1003
+ end
1004
+ end
1005
+
1006
+ if rev
1007
+ @@version[:rev] = rev
1008
+ @@version[:string] << "."
1009
+ @@version[:string] << rev[0...7] unless rev[0] == ?(
1010
+ end
1011
+
1012
+ @@version
1013
+ end
1014
+
1015
+ # Returns the path of file relative to the Haml root.
1016
+ def self.scope(file) # :nodoc:
1017
+ File.join(File.dirname(__FILE__), '..', file)
1018
+ end
1019
+
1020
+ # A string representing the version of Haml.
1021
+ # A more fine-grained representation is generated by Haml.version.
1022
+ VERSION = version[:string] unless defined?(Haml::VERSION)
1023
+
756
1024
  # This method is called by init.rb,
757
1025
  # which is run by Rails on startup.
758
1026
  # We use it rather than putting stuff straight into init.rb
759
1027
  # so we can change the initialization behavior
760
1028
  # without modifying the file itself.
761
1029
  def self.init_rails(binding)
762
- %w[haml/template sass sass/plugin].each(&method(:require))
1030
+ # No &method here for Rails 2.1 compatibility
1031
+ %w[haml/template sass sass/plugin].each {|f| require f}
763
1032
  end
764
1033
  end
765
1034