haml 4.0.7 → 5.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (124) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/test.yml +36 -0
  3. data/.gitignore +19 -0
  4. data/.gitmodules +3 -0
  5. data/.yardopts +2 -3
  6. data/CHANGELOG.md +146 -4
  7. data/FAQ.md +4 -14
  8. data/Gemfile +16 -0
  9. data/MIT-LICENSE +2 -2
  10. data/README.md +90 -47
  11. data/REFERENCE.md +160 -74
  12. data/Rakefile +44 -63
  13. data/TODO +24 -0
  14. data/benchmark.rb +70 -0
  15. data/haml.gemspec +45 -0
  16. data/lib/haml/.gitattributes +1 -0
  17. data/lib/haml/attribute_builder.rb +219 -0
  18. data/lib/haml/attribute_compiler.rb +237 -0
  19. data/lib/haml/attribute_parser.rb +150 -0
  20. data/lib/haml/buffer.rb +12 -175
  21. data/lib/haml/compiler.rb +110 -320
  22. data/lib/haml/engine.rb +34 -41
  23. data/lib/haml/error.rb +28 -24
  24. data/lib/haml/escapable.rb +77 -0
  25. data/lib/haml/exec.rb +38 -20
  26. data/lib/haml/filters.rb +22 -27
  27. data/lib/haml/generator.rb +42 -0
  28. data/lib/haml/helpers/action_view_extensions.rb +4 -2
  29. data/lib/haml/helpers/action_view_mods.rb +45 -60
  30. data/lib/haml/helpers/action_view_xss_mods.rb +2 -0
  31. data/lib/haml/helpers/safe_erubi_template.rb +20 -0
  32. data/lib/haml/helpers/safe_erubis_template.rb +5 -1
  33. data/lib/haml/helpers/xss_mods.rb +23 -13
  34. data/lib/haml/helpers.rb +134 -89
  35. data/lib/haml/options.rb +63 -69
  36. data/lib/haml/parser.rb +319 -227
  37. data/lib/haml/plugin.rb +54 -0
  38. data/lib/haml/railtie.rb +43 -12
  39. data/lib/haml/sass_rails_filter.rb +18 -4
  40. data/lib/haml/template/options.rb +13 -2
  41. data/lib/haml/template.rb +13 -6
  42. data/lib/haml/temple_engine.rb +124 -0
  43. data/lib/haml/temple_line_counter.rb +30 -0
  44. data/lib/haml/util.rb +83 -202
  45. data/lib/haml/version.rb +3 -1
  46. data/lib/haml.rb +2 -0
  47. data/yard/default/.gitignore +1 -0
  48. data/yard/default/fulldoc/html/css/common.sass +15 -0
  49. data/yard/default/layout/html/footer.erb +12 -0
  50. metadata +73 -115
  51. data/lib/haml/template/plugin.rb +0 -41
  52. data/test/engine_test.rb +0 -2013
  53. data/test/erb/_av_partial_1.erb +0 -12
  54. data/test/erb/_av_partial_2.erb +0 -8
  55. data/test/erb/action_view.erb +0 -62
  56. data/test/erb/standard.erb +0 -55
  57. data/test/filters_test.rb +0 -254
  58. data/test/gemfiles/Gemfile.rails-3.0.x +0 -5
  59. data/test/gemfiles/Gemfile.rails-3.1.x +0 -6
  60. data/test/gemfiles/Gemfile.rails-3.2.x +0 -5
  61. data/test/gemfiles/Gemfile.rails-4.0.x +0 -5
  62. data/test/haml-spec/LICENSE +0 -14
  63. data/test/haml-spec/README.md +0 -106
  64. data/test/haml-spec/lua_haml_spec.lua +0 -38
  65. data/test/haml-spec/perl_haml_test.pl +0 -81
  66. data/test/haml-spec/ruby_haml_test.rb +0 -23
  67. data/test/haml-spec/tests.json +0 -660
  68. data/test/helper_test.rb +0 -583
  69. data/test/markaby/standard.mab +0 -52
  70. data/test/mocks/article.rb +0 -6
  71. data/test/parser_test.rb +0 -105
  72. data/test/results/content_for_layout.xhtml +0 -12
  73. data/test/results/eval_suppressed.xhtml +0 -9
  74. data/test/results/helpers.xhtml +0 -70
  75. data/test/results/helpful.xhtml +0 -10
  76. data/test/results/just_stuff.xhtml +0 -70
  77. data/test/results/list.xhtml +0 -12
  78. data/test/results/nuke_inner_whitespace.xhtml +0 -40
  79. data/test/results/nuke_outer_whitespace.xhtml +0 -148
  80. data/test/results/original_engine.xhtml +0 -20
  81. data/test/results/partial_layout.xhtml +0 -5
  82. data/test/results/partial_layout_erb.xhtml +0 -5
  83. data/test/results/partials.xhtml +0 -21
  84. data/test/results/render_layout.xhtml +0 -3
  85. data/test/results/silent_script.xhtml +0 -74
  86. data/test/results/standard.xhtml +0 -162
  87. data/test/results/tag_parsing.xhtml +0 -23
  88. data/test/results/very_basic.xhtml +0 -5
  89. data/test/results/whitespace_handling.xhtml +0 -90
  90. data/test/template_test.rb +0 -354
  91. data/test/templates/_av_partial_1.haml +0 -9
  92. data/test/templates/_av_partial_1_ugly.haml +0 -9
  93. data/test/templates/_av_partial_2.haml +0 -5
  94. data/test/templates/_av_partial_2_ugly.haml +0 -5
  95. data/test/templates/_layout.erb +0 -3
  96. data/test/templates/_layout_for_partial.haml +0 -3
  97. data/test/templates/_partial.haml +0 -8
  98. data/test/templates/_text_area.haml +0 -3
  99. data/test/templates/_text_area_helper.html.haml +0 -4
  100. data/test/templates/action_view.haml +0 -47
  101. data/test/templates/action_view_ugly.haml +0 -47
  102. data/test/templates/breakage.haml +0 -8
  103. data/test/templates/content_for_layout.haml +0 -8
  104. data/test/templates/eval_suppressed.haml +0 -11
  105. data/test/templates/helpers.haml +0 -55
  106. data/test/templates/helpful.haml +0 -11
  107. data/test/templates/just_stuff.haml +0 -85
  108. data/test/templates/list.haml +0 -12
  109. data/test/templates/nuke_inner_whitespace.haml +0 -32
  110. data/test/templates/nuke_outer_whitespace.haml +0 -144
  111. data/test/templates/original_engine.haml +0 -17
  112. data/test/templates/partial_layout.haml +0 -3
  113. data/test/templates/partial_layout_erb.erb +0 -4
  114. data/test/templates/partialize.haml +0 -1
  115. data/test/templates/partials.haml +0 -12
  116. data/test/templates/render_layout.haml +0 -2
  117. data/test/templates/silent_script.haml +0 -45
  118. data/test/templates/standard.haml +0 -43
  119. data/test/templates/standard_ugly.haml +0 -43
  120. data/test/templates/tag_parsing.haml +0 -21
  121. data/test/templates/very_basic.haml +0 -4
  122. data/test/templates/whitespace_handling.haml +0 -87
  123. data/test/test_helper.rb +0 -81
  124. data/test/util_test.rb +0 -63
data/REFERENCE.md CHANGED
@@ -107,13 +107,25 @@ output.
107
107
  In Rails, options can be set by setting the {Haml::Template#options Haml::Template.options}
108
108
  hash in an initializer:
109
109
 
110
- # config/initializers/haml.rb
111
- Haml::Template.options[:format] = :html5
110
+ ```ruby
111
+ # config/initializers/haml.rb
112
+ Haml::Template.options[:format] = :html5
113
+
114
+ # Avoid escaping attributes which are already escaped
115
+ Haml::Template.options[:escape_attrs] = :once
116
+ ```
112
117
 
113
118
  Outside Rails, you can set them by configuring them globally in
114
119
  Haml::Options.defaults:
115
120
 
116
- Haml::Options.defaults[:format] = :html5
121
+ ```ruby
122
+ Haml::Options.defaults[:format] = :html5
123
+ ```
124
+
125
+ In sinatra specifically, you can set them in global config with:
126
+ ```ruby
127
+ set :haml, { escape_html: true }
128
+ ```
117
129
 
118
130
  Finally, you can also set them by passing an options hash to
119
131
  {Haml::Engine#initialize}. For the complete list of available options, please
@@ -121,7 +133,7 @@ see {Haml::Options}.
121
133
 
122
134
  ### Encodings
123
135
 
124
- When using Ruby 1.9 or later, Haml supports the same sorts of
136
+ Haml supports the same sorts of
125
137
  encoding-declaration comments that Ruby does. Although both Ruby and Haml
126
138
  support several different styles, the easiest it just to add `-# coding:
127
139
  encoding-name` at the beginning of the Haml template (it must come before all
@@ -223,18 +235,21 @@ is compiled to:
223
235
  <html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'></html>
224
236
 
225
237
  Attribute hashes can also be stretched out over multiple lines to accommodate
226
- many attributes. However, newlines may only be placed immediately after commas.
227
- For example:
238
+ many attributes.
228
239
 
229
- %script{:type => "text/javascript",
230
- :src => "javascripts/script_#{2 + 7}"}
240
+ %script{
241
+ "type": text/javascript",
242
+ "src": javascripts/script_#{2 + 7}",
243
+ "data": {
244
+ "controller": "reporter",
245
+ },
246
+ }
231
247
 
232
248
  is compiled to:
233
249
 
234
- <script src='javascripts/script_9' type='text/javascript'></script>
250
+ <script src='javascripts/script_9' type='text/javascript' data-controller='reporter'></script>
235
251
 
236
- #### `:class` and `:id` Attributes
237
- {#class-and-id-attributes}
252
+ #### `:class` and `:id` Attributes {#class-and-id-attributes}
238
253
 
239
254
  The `:class` and `:id` attributes can also be specified as a Ruby array whose
240
255
  elements will be joined together. A `:class` array is joined with `" "` and an
@@ -306,7 +321,7 @@ hash-style attributes:
306
321
 
307
322
  #### Ruby 1.9-style Hashes
308
323
 
309
- On Ruby 1.9, Haml also supports Ruby's new hash syntax:
324
+ Haml also supports Ruby's new hash syntax:
310
325
 
311
326
  %a{title: @title, href: href} Stuff
312
327
 
@@ -389,27 +404,49 @@ or using `true` and `false`:
389
404
 
390
405
  %input(selected=true)
391
406
 
392
- #### HTML5 Custom Data Attributes
407
+ <!-- The title to the next section (Prefixed Attributes) has changed. This
408
+ <a> tag is so old links to here still work. -->
409
+ <a id="html5_custom_data_attributes" style="border:0;"></a>
410
+
411
+ #### Prefixed Attributes
393
412
 
394
- HTML5 allows for adding [custom non-visible data
395
- attributes](http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#embedding-custom-non-visible-data)
396
- to elements using attribute names beginning with `data-`. Custom data attributes
397
- can be used in Haml by using the key `:data` with a Hash value in an attribute
398
- hash. Each of the key/value pairs in the Hash will be transformed into a custom
399
- data attribute. For example:
413
+ HTML5 allows for adding
414
+ [custom non-visible data attributes](http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
415
+ to elements using attribute names beginning with `data-`. The
416
+ [Accessible Rich Internet Applications](http://www.w3.org/WAI/intro/aria)
417
+ specification makes use of attributes beginning with `aria-`. There are also
418
+ frameworks that use non-standard attributes with a common prefix.
419
+
420
+ Haml can help generate collections of attributes that share a prefix like
421
+ these. Any entry in an attribute hash that has a Hash as its value is expanded
422
+ into a series of attributes, one for each key/value pair in the hash, with the
423
+ attribute name formed by joining the “parent” key name to the key name with a
424
+ hyphen.
425
+
426
+ For example:
400
427
 
401
- %a{:href=>"/posts", :data => {:author_id => 123}} Posts By Author
428
+ %a{:href=>"/posts", :data => {:author_id => 123, :category => 7}} Posts By Author
402
429
 
403
430
  will render as:
404
431
 
405
- <a data-author-id='123' href='/posts'>Posts By Author</a>
432
+ <a data-author-id='123' data-category='7' href='/posts'>Posts By Author</a>
406
433
 
407
434
  Notice that the underscore in `author_id` was replaced by a hyphen. If you wish
408
435
  to suppress this behavior, you can set Haml's
409
436
  {Haml::Options#hyphenate_data_attrs `:hyphenate_data_attrs` option} to `false`,
410
437
  and the output will be rendered as:
411
438
 
412
- <a data-author_id='123' href='/posts'>Posts By Author</a>
439
+ <a data-author_id='123' data-category='7' href='/posts'>Posts By Author</a>
440
+
441
+ This expansion of hashes is recursive – any value of the child hash that is
442
+ itself a hash will create an attribute for each entry, with the attribute name
443
+ prefixed with all ancestor keys. For example:
444
+
445
+ .book-info{:data => {:book => {:id => 123, :genre => 'programming'}, :category => 7}}
446
+
447
+ will render as:
448
+
449
+ <div class='book-info' data-book-genre='programming' data-book-id='123' data-category='7'></div>
413
450
 
414
451
  ### Class and ID: `.` and `#`
415
452
 
@@ -491,28 +528,46 @@ and is compiled to:
491
528
  </div>
492
529
  </div>
493
530
 
531
+ #### Class Name Merging and Ordering
532
+
533
+ Class names are ordered in the following way:
534
+
535
+ 1) Tag identifiers in order (aka, ".alert.me" => "alert me")
536
+ 2) Classes appearing in HTML-style attributes
537
+ 3) Classes appearing in Hash-style attributes
538
+
539
+ For instance, this is a complicated and unintuitive test case illustrating the ordering
540
+
541
+ .foo.moo{:class => ['bar', 'alpha']}(class='baz')
542
+
543
+ The resulting HTML would be as follows:
544
+
545
+ <div class='foo moo baz bar alpha'></div>
546
+
547
+ *Versions of Haml prior to 5.0 would alphabetically sort class names.*
548
+
494
549
  ### Empty (void) Tags: `/`
495
550
 
496
551
  The forward slash character, when placed at the end of a tag definition, causes
497
552
  Haml to treat it as being an empty (or void) element. Depending on the format,
498
553
  the tag will be rendered either without a closing tag (`:html4` or `:html5`), or
499
- as a self-closing tag (`:xhtml`). For example:
554
+ as a self-closing tag (`:xhtml`).
555
+
556
+ Taking the following as an example:
500
557
 
501
558
  %br/
502
559
  %meta{'http-equiv' => 'Content-Type', :content => 'text/html'}/
503
560
 
504
- is compiled to:
561
+ When the format is `:html4` or `:html5` this is compiled to:
505
562
 
506
563
  <br>
507
564
  <meta content='text/html' http-equiv='Content-Type'>
508
565
 
509
- when the format is `:html4` or `:html5`, and to
566
+ and when the format is `:xhtml` it is compiled to:
510
567
 
511
568
  <br />
512
569
  <meta content='text/html' http-equiv='Content-Type' />
513
570
 
514
- when the format is `:xhtml`.
515
-
516
571
  Some tags are automatically treated as being empty, as long as they have no
517
572
  content in the Haml source. `meta`, `img`, `link`, `br`, `hr`, `input`,
518
573
  `area`, `param`, `col` and `base` tags are treated as empty by default. This
@@ -779,6 +834,21 @@ is compiled to:
779
834
  </a>
780
835
  <![endif]-->
781
836
 
837
+ To generate “downlevel-revealed” conditional comments, where the content is
838
+ hidden from IE but not other browsers, add a `!` before the brackets: `/![]`.
839
+ Haml will produce valid HTML when generating this kind of conditional comment.
840
+
841
+ For example:
842
+
843
+ /![if !IE]
844
+ You are not using Internet Explorer, or are using version 10+.
845
+
846
+ is compiled to:
847
+
848
+ <!--[if !IE]><!-->
849
+ You are not using Internet Explorer, or are using version 10+.
850
+ <!--<![endif]-->
851
+
782
852
  ### Haml Comments: `-#`
783
853
 
784
854
  The hyphen followed immediately by the pound sign signifies a silent comment.
@@ -812,7 +882,7 @@ is compiled to:
812
882
 
813
883
  ## Ruby Evaluation
814
884
 
815
- ### Inserting Ruby: `=`
885
+ ### Inserting Ruby: `=` {#inserting_ruby}
816
886
 
817
887
  The equals character is followed by Ruby code. This code is evaluated and the
818
888
  output is inserted into the document. For example:
@@ -985,6 +1055,21 @@ might compile to:
985
1055
  //]]>
986
1056
  </script>
987
1057
 
1058
+ #### Gotchas
1059
+
1060
+ Haml uses an overly simplistic regular expression to identify string
1061
+ interpolation rather than a full-blown Ruby parser. This is fast and works for
1062
+ most code but you may have errors with code like the following:
1063
+
1064
+ %span #{'{'}
1065
+
1066
+ This code will generate a syntax error, complaining about unbalanced brackets.
1067
+ In cases like this, the recommended workaround is output the code as a Ruby
1068
+ string to force Haml to parse the code with Ruby.
1069
+
1070
+ %span= "#{'{'}"
1071
+
1072
+
988
1073
  ### Escaping HTML: `&=` {#escaping_html}
989
1074
 
990
1075
  An ampersand followed by one or two equals characters evaluates Ruby code just
@@ -1069,8 +1154,8 @@ is compiled to
1069
1154
  <p>I <strong>really</strong> prefer <em>raspberry</em> jam.</p>
1070
1155
  </div>
1071
1156
 
1072
- Currently, filters ignore the {Haml::Options#escape_html `:escape_html`} option.
1073
- This means that `#{}` interpolation within filters is never HTML-escaped.
1157
+ Note that `#{}` interpolation within filters is HTML-escaped if you specify true to
1158
+ {Haml::Options#escape_filter_interpolations `:escape_filter_interpolations`} option.
1074
1159
 
1075
1160
  The functionality of some filters such as Markdown can be provided by many
1076
1161
  different libraries. Usually you don't have to worry about this - you can just
@@ -1087,53 +1172,53 @@ more info.
1087
1172
 
1088
1173
  Haml comes with the following filters defined:
1089
1174
 
1090
- {#cdata-filter}
1091
- ### `:cdata`
1175
+ ### `:cdata` {#cdata-filter}
1176
+
1092
1177
  Surrounds the filtered text with CDATA tags.
1093
1178
 
1094
- {#coffee-filter}
1095
- ### `:coffee`
1096
- Compiles the filtered text to Javascript using Cofeescript. You can also
1097
- reference this filter as `:coffeescript`. This filter is implemented using
1098
- Tilt.
1179
+ ### `:coffee` {#coffee-filter}
1180
+
1181
+ Compiles the filtered text to JavaScript in `<script>` tag using CoffeeScript.
1182
+ You can also reference this filter as `:coffeescript`. This filter is
1183
+ implemented using Tilt.
1184
+
1185
+ ### `:css` {#css-filter}
1099
1186
 
1100
- {#css-filter}
1101
- ### `:css`
1102
1187
  Surrounds the filtered text with `<style>` and (optionally) CDATA tags. Useful
1103
1188
  for including inline CSS. Use the {Haml::Options#cdata `:cdata` option} to
1104
1189
  control when CDATA tags are added.
1105
1190
 
1106
- {#erb-filter}
1107
- ### `:erb`
1108
- Parses the filtered text with ERb, like an RHTML template. Not available if the
1191
+ ### `:erb` {#erb-filter}
1192
+
1193
+ Parses the filtered text with ERB, like an RHTML template. Not available if the
1109
1194
  {Haml::Options#suppress_eval `:suppress_eval`} option is set to true. Embedded
1110
1195
  Ruby code is evaluated in the same context as the Haml template. This filter is
1111
1196
  implemented using Tilt.
1112
1197
 
1113
- {#escaped-filter}
1114
- ### `:escaped`
1198
+ ### `:escaped` {#escaped-filter}
1199
+
1115
1200
  Works the same as plain, but HTML-escapes the text
1116
1201
  before placing it in the document.
1117
1202
 
1118
- {#javascript-filter}
1119
- ### `:javascript`
1203
+ ### `:javascript` {#javascript-filter}
1204
+
1120
1205
  Surrounds the filtered text with `<script>` and (optionally) CDATA tags.
1121
1206
  Useful for including inline Javascript. Use the {Haml::Options#cdata `:cdata`
1122
1207
  option} to control when CDATA tags are added.
1123
1208
 
1124
- {#less-filter}
1125
- ### `:less`
1126
- Parses the filtered text with [Less](http://lesscss.org/) to produce CSS output.
1209
+ ### `:less` {#less-filter}
1210
+
1211
+ Parses the filtered text with [Less](http://lesscss.org/) to produce CSS output in `<style>` tag.
1127
1212
  This filter is implemented using Tilt.
1128
1213
 
1129
- {#markdown-filter}
1130
- ### `:markdown`
1214
+ ### `:markdown` {#markdown-filter}
1215
+
1131
1216
  Parses the filtered text with
1132
1217
  [Markdown](http://daringfireball.net/projects/markdown). This filter is
1133
1218
  implemented using Tilt.
1134
1219
 
1135
- {#maruku-filter}
1136
- ### `:maruku`
1220
+ ### `:maruku` {#maruku-filter}
1221
+
1137
1222
  Parses the filtered text with [Maruku](https://github.com/nex3/maruku), which
1138
1223
  has some non-standard extensions to Markdown.
1139
1224
 
@@ -1142,39 +1227,40 @@ contrib](https://github.com/haml/haml-contrib) but is loaded automatically for
1142
1227
  historical reasons. In future versions of Haml it will likely not be loaded by
1143
1228
  default. This filter is implemented using Tilt.
1144
1229
 
1145
- {#plain-filter}
1146
- ### `:plain`
1230
+ ### `:plain` {#plain-filter}
1231
+
1147
1232
  Does not parse the filtered text. This is useful for large blocks of text
1148
1233
  without HTML tags, when you don't want lines starting with `.` or `-` to be
1149
1234
  parsed.
1150
1235
 
1151
- {#preserve-filter}
1152
- ### `:preserve`
1236
+ ### `:preserve` {#preserve-filter}
1237
+
1153
1238
  Inserts the filtered text into the template with whitespace preserved.
1154
1239
  `preserve`d blocks of text aren't indented, and newlines are replaced with the
1155
1240
  HTML escape code for newlines, to preserve nice-looking output. See also
1156
1241
  [Whitespace Preservation](#whitespace_preservation).
1157
1242
 
1158
- {#ruby-filter}
1159
- ### `:ruby`
1243
+ ### `:ruby` {#ruby-filter}
1244
+
1160
1245
  Parses the filtered text with the normal Ruby interpreter. Creates an `IO`
1161
1246
  object named `haml_io`, anything written to it is output into the Haml document.
1162
1247
  Not available if the {Haml::Options#suppress_eval `:suppress_eval`} option is
1163
1248
  set to true. The Ruby code is evaluated in the same context as the Haml
1164
1249
  template.
1165
1250
 
1166
- {#sass-filter}
1167
- ### `:sass`
1251
+ ### `:sass` {#sass-filter}
1252
+
1168
1253
  Parses the filtered text with [Sass](http://sass-lang.com/) to produce CSS
1169
- output. This filter is implemented using Tilt.
1254
+ output in `<style>` tag. This filter is implemented using Tilt.
1255
+
1256
+ ### `:scss` {#scss-filter}
1170
1257
 
1171
- {#scss-filter}
1172
- ### `:scss`
1173
1258
  Parses the filtered text with Sass like the `:sass` filter, but uses the newer
1174
- SCSS syntax to produce CSS output. This filter is implemented using Tilt.
1259
+ SCSS syntax to produce CSS output in `<style>` tag. This filter is implemented
1260
+ using Tilt.
1261
+
1262
+ ### `:textile` {#textile-filter}
1175
1263
 
1176
- {#textile-filter}
1177
- ### `:textile`
1178
1264
  Parses the filtered text with [Textile](http://www.textism.com/tools/textile).
1179
1265
  Only works if [RedCloth](http://redcloth.org) is installed.
1180
1266
 
@@ -1194,8 +1280,8 @@ the whitespace removal methods allow. There are a few helper methods that are
1194
1280
  useful when dealing with inline content. All these methods take a Haml block to
1195
1281
  modify.
1196
1282
 
1197
- {#surround}
1198
- ### surround
1283
+ ### surround {#surround}
1284
+
1199
1285
  Surrounds a Haml block with text. Expects 1 or 2 string arguments used to
1200
1286
  surround the Haml block. If a second argument is not provided, the first
1201
1287
  argument is used as the second.
@@ -1203,15 +1289,15 @@ argument is used as the second.
1203
1289
  = surround "(", ")" do
1204
1290
  = link_to "learn more", "#"
1205
1291
 
1206
- {#precede}
1207
- ### precede
1292
+ ### precede {#precede}
1293
+
1208
1294
  Prepends a Haml block with text. Expects 1 argument.
1209
1295
 
1210
1296
  = precede "*" do
1211
1297
  %span Required
1212
1298
 
1213
- {#succeed}
1214
- ### succeed
1299
+ ### succeed {#succeed}
1300
+
1215
1301
  Appends a Haml block with text. Expects 1 argument.
1216
1302
 
1217
1303
  Begin by
@@ -1266,7 +1352,7 @@ that just need a lot of template information.
1266
1352
  So data structures and functions that require lots of arguments
1267
1353
  can be wrapped over multiple lines,
1268
1354
  as long as each line but the last ends in a comma
1269
- (see [Inserting Ruby](#inserting_ruby_)).
1355
+ (see [Inserting Ruby](#inserting_ruby)).
1270
1356
 
1271
1357
  ## Whitespace Preservation
1272
1358
 
data/Rakefile CHANGED
@@ -1,43 +1,29 @@
1
1
  require "rake/clean"
2
2
  require "rake/testtask"
3
- require "rubygems/package_task"
3
+ require "bundler/gem_tasks"
4
4
 
5
5
  task :default => :test
6
6
 
7
- CLEAN.replace %w(pkg doc coverage .yardoc test/haml vendor)
8
-
9
- def silence_warnings
10
- the_real_stderr, $stderr = $stderr, StringIO.new
11
- yield
12
- ensure
13
- $stderr = the_real_stderr
14
- end
15
-
16
- desc "Benchmark Haml against ERb. TIMES=n sets the number of runs, default is 1000."
17
- task :benchmark do
18
- sh "ruby benchmark.rb #{ENV['TIMES']}"
7
+ # FIXME: Redefining :test task to run test/options_test.rb in isolated process since it depends on whether Rails is loaded or not.
8
+ # Remove this task when we finished changing escape_html option to be true by default.
9
+ isolated_test = Rake::TestTask.new do |t|
10
+ t.libs << 'test'
11
+ t.test_files = %w[test/options_test.rb]
12
+ t.warning = true
13
+ t.verbose = true
19
14
  end
20
-
21
15
  Rake::TestTask.new do |t|
22
- t.libs << 'lib' << 'test'
23
- # haml-spec tests are explicitly added after other tests so they don't
24
- # interfere with the Haml loading process which can cause test failures
25
- files = Dir["test/*_test.rb"]
26
- files.concat(Dir['test/haml-spec/*_test.rb'])
27
- t.test_files = files
16
+ t.libs << 'test'
17
+ t.test_files = Dir['test/*_test.rb'] + Dir['test/haml-spec/*_test.rb'] + Dir['test/cases/*_test.rb'] - isolated_test.file_list
18
+ t.warning = true
28
19
  t.verbose = true
29
20
  end
30
21
 
31
- task :set_coverage_env do
32
- ENV["COVERAGE"] = "true"
33
- end
34
-
35
- desc "Run Simplecov (only works on 1.9)"
36
- task :coverage => [:set_coverage_env, :test]
22
+ CLEAN.replace %w(pkg doc coverage .yardoc test/haml vendor)
37
23
 
38
- gemspec = File.expand_path("../haml.gemspec", __FILE__)
39
- if File.exist? gemspec
40
- Gem::PackageTask.new(eval(File.read(gemspec))) { |pkg| }
24
+ desc "Benchmark Haml against ERB. TIMES=n sets the number of runs, default is 1000."
25
+ task :benchmark do
26
+ sh "ruby benchmark.rb #{ENV['TIMES']}"
41
27
  end
42
28
 
43
29
  task :submodules do
@@ -47,31 +33,32 @@ task :submodules do
47
33
  end
48
34
  end
49
35
 
50
- begin
51
- silence_warnings do
52
- require 'yard'
53
- end
54
-
55
- namespace :doc do
56
- desc "List all undocumented methods and classes."
57
- task :undocumented do
58
- command = 'yard --list --query '
59
- command << '"object.docstring.blank? && '
60
- command << '!(object.type == :method && object.is_alias?)"'
61
- sh command
36
+ namespace :doc do
37
+ task :sass do
38
+ require 'sass'
39
+ Dir["yard/default/**/*.sass"].each do |sass|
40
+ File.open(sass.gsub(/sass$/, 'css'), 'w') do |f|
41
+ f.write(Sass::Engine.new(File.read(sass)).render)
42
+ end
62
43
  end
63
44
  end
64
45
 
65
- desc "Generate documentation"
66
- task(:doc) {sh "yard"}
46
+ desc "List all undocumented methods and classes."
47
+ task :undocumented do
48
+ command = 'yard --list --query '
49
+ command << '"object.docstring.blank? && '
50
+ command << '!(object.type == :method && object.is_alias?)"'
51
+ sh command
52
+ end
53
+ end
67
54
 
68
- desc "Generate documentation incrementally"
69
- task(:redoc) {sh "yard -c"}
55
+ desc "Generate documentation"
56
+ task(:doc => 'doc:sass') {sh "yard"}
70
57
 
71
- rescue LoadError
72
- end
58
+ desc "Generate documentation incrementally"
59
+ task(:redoc) {sh "yard -c"}
73
60
 
74
- desc <<END
61
+ desc <<END
75
62
  Profile Haml.
76
63
  TIMES=n sets the number of runs. Defaults to 1000.
77
64
  FILE=str sets the file to profile. Defaults to 'standard'
@@ -80,37 +67,31 @@ Profile Haml.
80
67
  END
81
68
  task :profile do
82
69
  times = (ENV['TIMES'] || '1000').to_i
83
- file = ENV['FILE']
70
+ file = ENV['FILE'] || 'test/templates/standard.haml'
84
71
 
85
72
  require 'bundler/setup'
86
73
  require 'ruby-prof'
87
74
  require 'haml'
88
-
89
- file = File.read(File.expand_path("../test/templates/#{file || 'standard'}.haml", __FILE__))
75
+ file = File.read(File.expand_path("../#{file}", __FILE__))
90
76
  obj = Object.new
91
- Haml::Engine.new(file, :ugly => true).def_method(obj, :render)
77
+ Haml::Engine.new(file).def_method(obj, :render)
92
78
  result = RubyProf.profile { times.times { obj.render } }
93
79
 
94
80
  RubyProf.const_get("#{(ENV['OUTPUT'] || 'Flat').capitalize}Printer").new(result).print
95
81
  end
96
82
 
97
83
  def gemfiles
98
- @gemfiles ||= begin
99
- Dir[File.dirname(__FILE__) + '/test/gemfiles/Gemfile.*'].
100
- reject {|f| f =~ /\.lock$/}.
101
- reject {|f| RUBY_VERSION < '1.9.3' && f =~ /Gemfile.rails-(\d+).\d+.x/ && $1.to_i > 3}
102
- end
84
+ @gemfiles ||= Dir[File.dirname(__FILE__) + '/test/gemfiles/Gemfile.*'].reject {|f| f =~ /\.lock$/}
103
85
  end
104
86
 
105
87
  def with_each_gemfile
106
- old_env = ENV['BUNDLE_GEMFILE']
107
88
  gemfiles.each do |gemfile|
108
- puts "Using gemfile: #{gemfile}"
109
- ENV['BUNDLE_GEMFILE'] = gemfile
110
- yield
89
+ Bundler.with_clean_env do
90
+ puts "Using gemfile: #{gemfile}"
91
+ ENV['BUNDLE_GEMFILE'] = gemfile
92
+ yield
93
+ end
111
94
  end
112
- ensure
113
- ENV['BUNDLE_GEMFILE'] = old_env
114
95
  end
115
96
 
116
97
  namespace :test do
data/TODO ADDED
@@ -0,0 +1,24 @@
1
+ # -*- mode: org -*-
2
+ #+STARTUP: nofold
3
+
4
+ * Documentation
5
+ Redo tutorial?
6
+ Using helpers
7
+ haml_concat and haml_tag in particular
8
+ Syntax highlighting?
9
+
10
+ * Code
11
+ Keep track of error offsets everywhere
12
+ Use this to show error location in messages
13
+ ** Haml
14
+ Support finer-grained HTML-escaping in filters
15
+ Speed
16
+ Make tags with dynamic attributes pre-render as much as possible
17
+ Including the attribute name where doable
18
+ :html improvements
19
+ Ignore closing tags where we can
20
+ http://code.google.com/speed/articles/optimizing-html.html
21
+ Requires Haml parsing refactor
22
+ Don't quote attributes that don't require it
23
+ http://www.w3.org/TR/REC-html40/intro/sgmltut.html#h-3.2.2
24
+ http://www.w3.org/TR/html5/syntax.html#attributes
data/benchmark.rb ADDED
@@ -0,0 +1,70 @@
1
+ require "bundler/setup"
2
+ require "haml"
3
+ require "rbench"
4
+
5
+ times = (ARGV.first || 1000).to_i
6
+
7
+ if times == 0 # Invalid parameter
8
+ puts <<END
9
+ ruby #$0 [times=1000]
10
+ Benchmark Haml against various other templating languages.
11
+ END
12
+ exit 1
13
+ end
14
+
15
+ %w[erb erubi rails active_support action_controller
16
+ action_view action_pack haml/template rbench].each {|dep| require(dep)}
17
+
18
+ def view
19
+ base = ActionView::Base.new
20
+ base.view_paths << File.join(File.dirname(__FILE__), '/test')
21
+ base
22
+ end
23
+
24
+ def render(view, file)
25
+ view.render :file => file
26
+ end
27
+
28
+ RBench.run(times) do
29
+ column :haml, :title => "Haml"
30
+ column :erb, :title => "ERB"
31
+ column :erubi, :title => "Erubi"
32
+
33
+ template_name = 'standard'
34
+ haml_template = File.read("#{File.dirname(__FILE__)}/test/templates/#{template_name}.haml")
35
+ erb_template = File.read("#{File.dirname(__FILE__)}/test/erb/#{template_name}.erb")
36
+
37
+ report "Cached" do
38
+ obj = Object.new
39
+
40
+ Haml::Engine.new(haml_template).def_method(obj, :haml)
41
+ if ERB.instance_method(:initialize).parameters.assoc(:key) # Ruby 2.6+
42
+ obj.instance_eval("def erb; #{ERB.new(erb_template, trim_mode: '-').src}; end")
43
+ else
44
+ obj.instance_eval("def erb; #{ERB.new(erb_template, nil, '-').src}; end")
45
+ end
46
+ obj.instance_eval("def erubi; #{Erubi::Engine.new(erb_template).src}; end")
47
+
48
+ haml { obj.haml }
49
+ erb { obj.erb }
50
+ erubi { obj.erubi }
51
+ end
52
+
53
+ report "ActionView" do
54
+ # To cache the template
55
+ render view, 'templates/standard'
56
+ render view, 'erb/standard'
57
+
58
+ haml { render view, 'templates/standard' }
59
+ erubi { render view, 'erb/standard' }
60
+ end
61
+
62
+ report "ActionView with deep partials" do
63
+ # To cache the template
64
+ render view, 'templates/action_view'
65
+ render view, 'erb/action_view'
66
+
67
+ haml { render view, 'templates/action_view' }
68
+ erubi { render view, 'erb/action_view' }
69
+ end
70
+ end