haml 5.2.2 → 6.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +3 -0
  3. data/.github/workflows/test.yml +15 -15
  4. data/.gitignore +16 -16
  5. data/.yardopts +0 -3
  6. data/CHANGELOG.md +168 -4
  7. data/FAQ.md +1 -1
  8. data/Gemfile +21 -10
  9. data/MIT-LICENSE +1 -1
  10. data/README.md +22 -34
  11. data/REFERENCE.md +95 -159
  12. data/Rakefile +15 -82
  13. data/bin/bench +66 -0
  14. data/bin/console +11 -0
  15. data/bin/ruby +3 -0
  16. data/bin/setup +7 -0
  17. data/bin/stackprof +27 -0
  18. data/bin/test +24 -0
  19. data/exe/haml +6 -0
  20. data/haml.gemspec +34 -36
  21. data/lib/haml/ambles.rb +20 -0
  22. data/lib/haml/attribute_builder.rb +127 -184
  23. data/lib/haml/attribute_compiler.rb +90 -194
  24. data/lib/haml/attribute_parser.rb +92 -126
  25. data/lib/haml/cli.rb +154 -0
  26. data/lib/haml/compiler/children_compiler.rb +155 -0
  27. data/lib/haml/compiler/comment_compiler.rb +51 -0
  28. data/lib/haml/compiler/doctype_compiler.rb +52 -0
  29. data/lib/haml/compiler/script_compiler.rb +114 -0
  30. data/lib/haml/compiler/silent_script_compiler.rb +24 -0
  31. data/lib/haml/compiler/tag_compiler.rb +76 -0
  32. data/lib/haml/compiler.rb +63 -296
  33. data/lib/haml/dynamic_merger.rb +67 -0
  34. data/lib/haml/engine.rb +48 -227
  35. data/lib/haml/error.rb +5 -4
  36. data/lib/haml/escape.rb +13 -0
  37. data/lib/haml/escape_any.rb +21 -0
  38. data/lib/haml/filters/base.rb +12 -0
  39. data/lib/haml/filters/cdata.rb +20 -0
  40. data/lib/haml/filters/coffee.rb +17 -0
  41. data/lib/haml/filters/css.rb +33 -0
  42. data/lib/haml/filters/erb.rb +10 -0
  43. data/lib/haml/filters/escaped.rb +22 -0
  44. data/lib/haml/filters/javascript.rb +33 -0
  45. data/lib/haml/filters/less.rb +20 -0
  46. data/lib/haml/filters/markdown.rb +11 -0
  47. data/lib/haml/filters/plain.rb +29 -0
  48. data/lib/haml/filters/preserve.rb +22 -0
  49. data/lib/haml/filters/ruby.rb +10 -0
  50. data/lib/haml/filters/sass.rb +15 -0
  51. data/lib/haml/filters/scss.rb +15 -0
  52. data/lib/haml/filters/text_base.rb +25 -0
  53. data/lib/haml/filters/tilt_base.rb +59 -0
  54. data/lib/haml/filters.rb +54 -378
  55. data/lib/haml/force_escape.rb +29 -0
  56. data/lib/haml/helpers.rb +3 -697
  57. data/lib/haml/html.rb +22 -0
  58. data/lib/haml/identity.rb +13 -0
  59. data/lib/haml/object_ref.rb +35 -0
  60. data/lib/haml/parser.rb +158 -23
  61. data/lib/haml/rails_helpers.rb +53 -0
  62. data/lib/haml/rails_template.rb +62 -0
  63. data/lib/haml/railtie.rb +3 -46
  64. data/lib/haml/ruby_expression.rb +32 -0
  65. data/lib/haml/string_splitter.rb +140 -0
  66. data/lib/haml/template.rb +15 -34
  67. data/lib/haml/temple_line_counter.rb +2 -1
  68. data/lib/haml/util.rb +19 -15
  69. data/lib/haml/version.rb +1 -2
  70. data/lib/haml/whitespace.rb +8 -0
  71. data/lib/haml.rb +8 -20
  72. metadata +188 -50
  73. data/.gitmodules +0 -3
  74. data/TODO +0 -24
  75. data/benchmark.rb +0 -70
  76. data/bin/haml +0 -9
  77. data/lib/haml/.gitattributes +0 -1
  78. data/lib/haml/buffer.rb +0 -182
  79. data/lib/haml/escapable.rb +0 -77
  80. data/lib/haml/exec.rb +0 -347
  81. data/lib/haml/generator.rb +0 -42
  82. data/lib/haml/helpers/action_view_extensions.rb +0 -60
  83. data/lib/haml/helpers/action_view_mods.rb +0 -132
  84. data/lib/haml/helpers/action_view_xss_mods.rb +0 -60
  85. data/lib/haml/helpers/safe_erubi_template.rb +0 -20
  86. data/lib/haml/helpers/safe_erubis_template.rb +0 -33
  87. data/lib/haml/helpers/xss_mods.rb +0 -114
  88. data/lib/haml/options.rb +0 -273
  89. data/lib/haml/plugin.rb +0 -54
  90. data/lib/haml/sass_rails_filter.rb +0 -47
  91. data/lib/haml/template/options.rb +0 -27
  92. data/lib/haml/temple_engine.rb +0 -124
  93. data/yard/default/.gitignore +0 -1
  94. data/yard/default/fulldoc/html/css/common.sass +0 -15
  95. data/yard/default/layout/html/footer.erb +0 -12
data/REFERENCE.md CHANGED
@@ -30,7 +30,7 @@ The first step for all of these is to install the Haml gem:
30
30
 
31
31
  To run Haml from the command line, just use
32
32
 
33
- haml input.haml output.html
33
+ haml render input.haml > output.html
34
34
 
35
35
  Use `haml --help` for full documentation.
36
36
 
@@ -68,24 +68,6 @@ may be compiled to:
68
68
  </div>
69
69
  </div>
70
70
 
71
- ### Rails XSS Protection
72
-
73
- Haml supports Rails' XSS protection scheme, which was introduced in Rails 2.3.5+
74
- and is enabled by default in 3.0.0+. If it's enabled, Haml's
75
- {Haml::Options#escape_html `:escape_html`} option is set to `true` by default -
76
- like in ERB, all strings printed to a Haml template are escaped by default. Also
77
- like ERB, strings marked as HTML safe are not escaped. Haml also has [its own
78
- syntax for printing a raw string to the template](#unescaping_html).
79
-
80
- If the `:escape_html` option is set to false when XSS protection is enabled,
81
- Haml doesn't escape Ruby strings by default. However, if a string marked
82
- HTML-safe is passed to [Haml's escaping syntax](#escaping_html), it won't be
83
- escaped.
84
-
85
- Finally, all the {Haml::Helpers Haml helpers} that return strings that are known
86
- to be HTML safe are marked as such. In addition, string input is escaped unless
87
- it's HTML safe.
88
-
89
71
  ### Ruby Module
90
72
 
91
73
  Haml can also be used completely separately from Rails and ActionView. To do
@@ -93,10 +75,10 @@ this, install the gem with RubyGems:
93
75
 
94
76
  gem install haml
95
77
 
96
- You can then use it by including the "haml" gem in Ruby code, and using
97
- {Haml::Engine} like so:
78
+ You can then use it by including the `haml` gem in Ruby code, and using
79
+ {Haml::Template} like so:
98
80
 
99
- engine = Haml::Engine.new("%p Haml code!")
81
+ engine = Haml::Template.new { "%p Haml code!" }
100
82
  engine.render #=> "<p>Haml code!</p>\n"
101
83
 
102
84
  ### Options
@@ -104,50 +86,26 @@ You can then use it by including the "haml" gem in Ruby code, and using
104
86
  Haml understands various configuration options that affect its performance and
105
87
  output.
106
88
 
107
- In Rails, options can be set by setting the {Haml::Template#options Haml::Template.options}
108
- hash in an initializer:
89
+ In Rails, options can be set by using `Haml::RailsTemplate.set_options` in an initializer:
109
90
 
110
91
  ```ruby
111
92
  # 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
93
+ Haml::RailsTemplate.set_options(escape_html: false)
116
94
  ```
117
95
 
118
- Outside Rails, you can set them by configuring them globally in
119
- Haml::Options.defaults:
96
+ Outside Rails, you can set them by configuring them globally in `Haml::Template.options`:
120
97
 
121
98
  ```ruby
122
- Haml::Options.defaults[:format] = :html5
99
+ Haml::Template.options[:escape_html] = false
123
100
  ```
124
101
 
125
102
  In sinatra specifically, you can set them in global config with:
126
103
  ```ruby
127
- set :haml, { escape_html: true }
104
+ set :haml, { escape_html: false }
128
105
  ```
129
106
 
130
- Finally, you can also set them by passing an options hash to
131
- {Haml::Engine#initialize}. For the complete list of available options, please
132
- see {Haml::Options}.
133
-
134
- ### Encodings
135
-
136
- Haml supports the same sorts of
137
- encoding-declaration comments that Ruby does. Although both Ruby and Haml
138
- support several different styles, the easiest it just to add `-# coding:
139
- encoding-name` at the beginning of the Haml template (it must come before all
140
- other lines). This will tell Haml that the template is encoded using the named
141
- encoding.
142
-
143
- By default, the HTML generated by Haml has the same encoding as the Haml
144
- template. However, if `Encoding.default_internal` is set, Haml will attempt to
145
- use that instead. In addition, the {Haml::Options#encoding `:encoding` option}
146
- can be used to specify an output encoding manually.
147
-
148
- Note that, like Ruby, Haml does not support templates encoded in UTF-16 or
149
- UTF-32, since these encodings are not compatible with ASCII. It is possible to
150
- use these as the output encoding, though.
107
+ Finally, you can also set them by passing an options hash to `Haml::Engine.new` or `Haml::Template.new`.
108
+ For the complete list of available options, please see `Haml::Engine`.
151
109
 
152
110
  ## Plain Text
153
111
 
@@ -222,10 +180,10 @@ closing tags for any element.
222
180
 
223
181
  ### Attributes: `{}` or `()` {#attributes}
224
182
 
225
- Brackets represent a Ruby hash that is used for specifying the attributes of an
183
+ Braces represent a Ruby hash that is used for specifying the attributes of an
226
184
  element. It is literally evaluated as a Ruby hash, so logic will work in it and
227
185
  local variables may be used. Quote characters within the attribute will be
228
- replaced by appropriate escape sequences. The hash is placed after the tag is
186
+ replaced with appropriate escape sequences. The hash is placed after the tag is
229
187
  defined. For example:
230
188
 
231
189
  %html{:xmlns => "http://www.w3.org/1999/xhtml", "xml:lang" => "en", :lang => "en"}
@@ -289,7 +247,7 @@ could render as either of:
289
247
  #### HTML-style Attributes: `()`
290
248
 
291
249
  Haml also supports a terser, less Ruby-specific attribute syntax based on HTML's
292
- attributes. These are used with parentheses instead of brackets, like so:
250
+ attributes. These are used with parentheses instead of braces, like so:
293
251
 
294
252
  %html(xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en")
295
253
 
@@ -325,49 +283,6 @@ Haml also supports Ruby's new hash syntax:
325
283
 
326
284
  %a{title: @title, href: href} Stuff
327
285
 
328
- #### Attribute Methods
329
-
330
- A Ruby method call that returns a hash can be substituted for the hash contents.
331
- For example, {Haml::Helpers} defines the following method:
332
-
333
- def html_attrs(lang = 'en-US')
334
- {:xmlns => "http://www.w3.org/1999/xhtml", 'xml:lang' => lang, :lang => lang}
335
- end
336
-
337
- This can then be used in Haml, like so:
338
-
339
- %html{html_attrs('fr-fr')}
340
-
341
- This is compiled to:
342
-
343
- <html lang='fr-fr' xml:lang='fr-fr' xmlns='http://www.w3.org/1999/xhtml'>
344
- </html>
345
-
346
- You can use as many such attribute methods as you want by separating them with
347
- commas, like a Ruby argument list. All the hashes will be merged together, from
348
- left to right. For example, if you defined
349
-
350
- def hash1
351
- {:bread => 'white', :filling => 'peanut butter and jelly'}
352
- end
353
-
354
- def hash2
355
- {:bread => 'whole wheat'}
356
- end
357
-
358
- then
359
-
360
- %sandwich{hash1, hash2, :delicious => 'true'}/
361
-
362
- would compile to:
363
-
364
- <sandwich bread='whole wheat' delicious='true' filling='peanut butter and jelly' />
365
-
366
- Note that the Haml attributes list has the same syntax as a Ruby method call.
367
- This means that any attribute methods must come before the hash literal.
368
-
369
- Attribute methods aren't supported for HTML-style attributes.
370
-
371
286
  #### Boolean Attributes
372
287
 
373
288
  Some attributes, such as "checked" for `input` tags or "selected" for `option`
@@ -404,24 +319,38 @@ or using `true` and `false`:
404
319
 
405
320
  %input(selected=true)
406
321
 
322
+ This feature works only for attributes that are included in
323
+ [`Haml::AttributeBuilder::BOOLEAN_ATTRIBUTES`](https://github.com/haml/haml/blob/main/lib/haml/attribute_builder.rb#L5),
324
+ as well as `data-` and `aria-` attributes.
325
+
326
+ %input{'data-hidden' => false}
327
+ %input{'aria-hidden' => false}
328
+ %input{'xyz-hidden' => false}
329
+
330
+ will render as:
331
+
332
+ <input>
333
+ <input>
334
+ <input xyz-hidden='false'>
335
+
336
+
407
337
  <!-- The title to the next section (Prefixed Attributes) has changed. This
408
338
  <a> tag is so old links to here still work. -->
409
339
  <a id="html5_custom_data_attributes" style="border:0;"></a>
410
340
 
411
- #### Prefixed Attributes
341
+ #### Data Attributes
412
342
 
413
343
  HTML5 allows for adding
414
344
  [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
345
  to elements using attribute names beginning with `data-`. The
416
346
  [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.
347
+ specification makes use of attributes beginning with `aria-`.
419
348
 
420
349
  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.
350
+ these. Any entry in an `data` or `aria` attribute hash that has a Hash as its
351
+ value is expanded into a series of attributes, one for each key/value pair in
352
+ the hash, with the attribute name formed by joining the “parent” key name to
353
+ the key name with a hyphen. This works only for `data` or `aria`.
425
354
 
426
355
  For example:
427
356
 
@@ -431,7 +360,7 @@ will render as:
431
360
 
432
361
  <a data-author-id='123' data-category='7' href='/posts'>Posts By Author</a>
433
362
 
434
- Notice that the underscore in `author_id` was replaced by a hyphen. If you wish
363
+ Notice that the underscore in `author_id` was replaced with a hyphen. If you wish
435
364
  to suppress this behavior, you can set Haml's
436
365
  {Haml::Options#hyphenate_data_attrs `:hyphenate_data_attrs` option} to `false`,
437
366
  and the output will be rendered as:
@@ -993,7 +922,7 @@ is compiled to:
993
922
 
994
923
  ### Whitespace Preservation: `~` {#tilde}
995
924
 
996
- `~` works just like `=`, except that it runs {Haml::Helpers#find\_and\_preserve}
925
+ `~` works just like `=`, except that it runs {Haml::Helpers.preserve}
997
926
  on its input. For example,
998
927
 
999
928
  ~ "Foo\n<pre>Bar\nBaz</pre>"
@@ -1063,7 +992,7 @@ most code but you may have errors with code like the following:
1063
992
 
1064
993
  %span #{'{'}
1065
994
 
1066
- This code will generate a syntax error, complaining about unbalanced brackets.
995
+ This code will generate a syntax error, complaining about unbalanced braces.
1067
996
  In cases like this, the recommended workaround is output the code as a Ruby
1068
997
  string to force Haml to parse the code with Ruby.
1069
998
 
@@ -1154,9 +1083,6 @@ is compiled to
1154
1083
  <p>I <strong>really</strong> prefer <em>raspberry</em> jam.</p>
1155
1084
  </div>
1156
1085
 
1157
- Note that `#{}` interpolation within filters is HTML-escaped if you specify true to
1158
- {Haml::Options#escape_filter_interpolations `:escape_filter_interpolations`} option.
1159
-
1160
1086
  The functionality of some filters such as Markdown can be provided by many
1161
1087
  different libraries. Usually you don't have to worry about this - you can just
1162
1088
  load the gem of your choice and Haml will automatically use it.
@@ -1167,7 +1093,7 @@ uses to implement many of its filters:
1167
1093
 
1168
1094
  Tilt.prefer Tilt::RedCarpetTemplate
1169
1095
 
1170
- See the [Tilt documentation](https://github.com/rtomayko/tilt#fallback-mode) for
1096
+ See the [Tilt documentation](https://github.com/rtomayko/tilt) for
1171
1097
  more info.
1172
1098
 
1173
1099
  Haml comes with the following filters defined:
@@ -1219,7 +1145,7 @@ implemented using Tilt.
1219
1145
 
1220
1146
  ### `:maruku` {#maruku-filter}
1221
1147
 
1222
- Parses the filtered text with [Maruku](https://github.com/nex3/maruku), which
1148
+ Parses the filtered text with [Maruku](https://github.com/bhollis/maruku), which
1223
1149
  has some non-standard extensions to Markdown.
1224
1150
 
1225
1151
  As of Haml 4.0, this filter is defined in [Haml
@@ -1242,11 +1168,8 @@ HTML escape code for newlines, to preserve nice-looking output. See also
1242
1168
 
1243
1169
  ### `:ruby` {#ruby-filter}
1244
1170
 
1245
- Parses the filtered text with the normal Ruby interpreter. Creates an `IO`
1246
- object named `haml_io`, anything written to it is output into the Haml document.
1247
- Not available if the {Haml::Options#suppress_eval `:suppress_eval`} option is
1248
- set to true. The Ruby code is evaluated in the same context as the Haml
1249
- template.
1171
+ Parses the filtered text with the normal Ruby interpreter.
1172
+ The Ruby code is evaluated in the same context as the Haml template.
1250
1173
 
1251
1174
  ### `:sass` {#sass-filter}
1252
1175
 
@@ -1271,43 +1194,44 @@ default. This filter is implemented using Tilt.
1271
1194
 
1272
1195
  ### Custom Filters
1273
1196
 
1274
- You can also define your own filters. See {Haml::Filters} for details.
1275
-
1276
- ## Helper Methods {#helper-methods}
1277
-
1278
- Sometimes you need to manipulate whitespace in a more precise fashion than what
1279
- the whitespace removal methods allow. There are a few helper methods that are
1280
- useful when dealing with inline content. All these methods take a Haml block to
1281
- modify.
1282
-
1283
- ### surround {#surround}
1284
-
1285
- Surrounds a Haml block with text. Expects 1 or 2 string arguments used to
1286
- surround the Haml block. If a second argument is not provided, the first
1287
- argument is used as the second.
1197
+ You can also define your own filters.
1198
+ `Haml::Filters::YourCustomFilter#compile` should return
1199
+ [a Temple expression](https://github.com/judofyr/temple/blob/master/EXPRESSIONS.md).
1288
1200
 
1289
- = surround "(", ")" do
1290
- = link_to "learn more", "#"
1201
+ The simplest example of a filter might be something like:
1291
1202
 
1292
- ### precede {#precede}
1293
-
1294
- Prepends a Haml block with text. Expects 1 argument.
1295
-
1296
- = precede "*" do
1297
- %span Required
1298
-
1299
- ### succeed {#succeed}
1203
+ class HelloFilter < Haml::Filters::Base
1204
+ def compile(_node)
1205
+ [:static, "hello world"]
1206
+ end
1207
+ end
1208
+
1209
+ Haml::Filters.registered[:hello] ||= HelloFilter
1210
+
1211
+ A more complex example:
1212
+
1213
+ class BetterFilter < Haml::Filters::Base
1214
+ def compile(node)
1215
+ temple = [:multi]
1216
+ temple << [:static, "hello "]
1217
+ temple << compile_text(node.value[:text])
1218
+ temple << [:static, " world"]
1219
+ temple
1220
+ end
1221
+
1222
+ private
1223
+ def compile_text(text)
1224
+ if ::Haml::Util.contains_interpolation?(text)
1225
+ [:dynamic, ::Haml::Util.unescape_interpolation(text)]
1226
+ else
1227
+ [:static, text]
1228
+ end
1229
+ end
1230
+ end
1300
1231
 
1301
- Appends a Haml block with text. Expects 1 argument.
1232
+ Haml::Filters.registered[:better] ||= BetterFilter
1302
1233
 
1303
- Begin by
1304
- = succeed "," do
1305
- = link_to "filling out your profile", "#"
1306
- = succeed "," do
1307
- = link_to "adding a bio", "#"
1308
- and
1309
- = succeed "." do
1310
- = link_to "inviting friends", "#"
1234
+ See {Haml::Filters} for examples.
1311
1235
 
1312
1236
  ## Multiline: `|` {#multiline}
1313
1237
 
@@ -1354,7 +1278,7 @@ can be wrapped over multiple lines,
1354
1278
  as long as each line but the last ends in a comma
1355
1279
  (see [Inserting Ruby](#inserting_ruby)).
1356
1280
 
1357
- ## Whitespace Preservation
1281
+ ## Whitespace Preservation {#whitespace_preservation}
1358
1282
 
1359
1283
  Sometimes you don't want Haml to indent all your text.
1360
1284
  For example, tags like `pre` and `textarea` are whitespace-sensitive;
@@ -1367,14 +1291,26 @@ Haml won't try to re-format the indentation.
1367
1291
  Literal `textarea` and `pre` tags automatically preserve content given through
1368
1292
  `=`. Dynamically-generated `textarea`s and `pre`s can't be preserved
1369
1293
  automatically, and so should be passed through
1370
- {Haml::Helpers#find\_and\_preserve} or the [`~` command](#tilde), which has the
1294
+ {Haml::Helpers.preserve} or the [`~` command](#tilde), which has the
1371
1295
  same effect.
1372
1296
 
1373
1297
  Blocks of literal text can be preserved using the [`:preserve` filter](#preserve-filter).
1374
1298
 
1375
- ## Helpers
1299
+ ## Turbo
1300
+
1301
+ For people using Turbo-rails and Haml 6+ need to either:
1302
+ * follow the naming convention with the html format (ie. ensure any `.haml` files end `.html.haml`), or
1303
+ * add a monkey patch as follows:
1304
+
1305
+ ```rb
1306
+ # config/initializers/haml.rb
1307
+ require "haml/rails_template"
1376
1308
 
1377
- Haml offers a bunch of helpers that are useful for doing stuff like preserving
1378
- whitespace, creating nicely indented output for user-defined helpers, and other
1379
- useful things. The helpers are all documented in the {Haml::Helpers} and
1380
- {Haml::Helpers::ActionViewExtensions} modules.
1309
+ module Haml
1310
+ class RailsTemplate
1311
+ def default_format
1312
+ :html
1313
+ end
1314
+ end
1315
+ end
1316
+ ```
data/Rakefile CHANGED
@@ -1,36 +1,23 @@
1
- require "rake/clean"
2
- require "rake/testtask"
3
- require "bundler/gem_tasks"
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
4
3
 
5
- task :default => :test
6
-
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
14
- end
15
4
  Rake::TestTask.new do |t|
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
5
+ t.libs << 'lib' << 'test'
6
+ files = Dir['test/haml/**/*_test.rb']
7
+ t.ruby_opts = %w[-rtest_helper]
8
+ t.test_files = files
19
9
  t.verbose = true
20
10
  end
11
+ task :test
21
12
 
22
- CLEAN.replace %w(pkg doc coverage .yardoc test/haml vendor)
23
-
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']}"
27
- end
28
-
29
- task :submodules do
30
- if File.exist?(File.dirname(__FILE__) + "/.git")
31
- sh %{git submodule sync}
32
- sh %{git submodule update --init --recursive}
13
+ desc 'bench task for CI'
14
+ task :bench do
15
+ if ENV['SLIM_BENCH'] == '1'
16
+ cmd = %w[bundle exec ruby benchmark/slim/run-benchmarks.rb]
17
+ else
18
+ cmd = ['bin/bench', 'bench', ('-c' if ENV['COMPILE'] == '1'), *ENV['TEMPLATE'].split(',')].compact
33
19
  end
20
+ exit system(*cmd)
34
21
  end
35
22
 
36
23
  namespace :doc do
@@ -58,58 +45,4 @@ task(:doc => 'doc:sass') {sh "yard"}
58
45
  desc "Generate documentation incrementally"
59
46
  task(:redoc) {sh "yard -c"}
60
47
 
61
- desc <<END
62
- Profile Haml.
63
- TIMES=n sets the number of runs. Defaults to 1000.
64
- FILE=str sets the file to profile. Defaults to 'standard'
65
- OUTPUT=str sets the ruby-prof output format.
66
- Can be Flat, CallInfo, or Graph. Defaults to Flat. Defaults to Flat.
67
- END
68
- task :profile do
69
- times = (ENV['TIMES'] || '1000').to_i
70
- file = ENV['FILE'] || 'test/templates/standard.haml'
71
-
72
- require 'bundler/setup'
73
- require 'ruby-prof'
74
- require 'haml'
75
- file = File.read(File.expand_path("../#{file}", __FILE__))
76
- obj = Object.new
77
- Haml::Engine.new(file).def_method(obj, :render)
78
- result = RubyProf.profile { times.times { obj.render } }
79
-
80
- RubyProf.const_get("#{(ENV['OUTPUT'] || 'Flat').capitalize}Printer").new(result).print
81
- end
82
-
83
- def gemfiles
84
- @gemfiles ||= Dir[File.dirname(__FILE__) + '/test/gemfiles/Gemfile.*'].reject {|f| f =~ /\.lock$/}
85
- end
86
-
87
- def with_each_gemfile
88
- gemfiles.each do |gemfile|
89
- Bundler.with_clean_env do
90
- puts "Using gemfile: #{gemfile}"
91
- ENV['BUNDLE_GEMFILE'] = gemfile
92
- yield
93
- end
94
- end
95
- end
96
-
97
- namespace :test do
98
- namespace :bundles do
99
- desc "Install all dependencies necessary to test Haml."
100
- task :install do
101
- with_each_gemfile {sh "bundle"}
102
- end
103
-
104
- desc "Update all dependencies for testing Haml."
105
- task :update do
106
- with_each_gemfile {sh "bundle update"}
107
- end
108
- end
109
-
110
- desc "Test all supported versions of rails. This takes a while."
111
- task :rails_compatibility => 'test:bundles:install' do
112
- with_each_gemfile {sh "bundle exec rake test"}
113
- end
114
- task :rc => :rails_compatibility
115
- end
48
+ task default: :test
data/bin/bench ADDED
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'haml'
5
+ require 'thor'
6
+ require 'benchmark/ips'
7
+ require_relative '../benchmark/utils/benchmark_ips_extension'
8
+
9
+ class Bench < Thor
10
+ class_option :show_template, type: :boolean, aliases: ['-t']
11
+
12
+ desc 'bench HAML', 'Benchmark haml template'
13
+ option :compile, type: :boolean, aliases: ['-c']
14
+ option :show_code, type: :boolean, aliases: ['-s']
15
+ def bench(*files)
16
+ files.each { |file| render(file) }
17
+ files.each { |file| compile(file) if options[:compile] }
18
+ files.each { |file| code(file) if options[:show_code] }
19
+ end
20
+
21
+ desc 'compile HAML', 'Benchmark compilation'
22
+ def compile(file)
23
+ puts "#{?= * 49}\n Compilation: #{file}\n#{?= * 49}"
24
+ haml = File.read(file)
25
+
26
+ Benchmark.ips do |x|
27
+ x.report("haml v#{Haml::VERSION}") { Haml::Engine.new.call(haml) }
28
+ x.compare!
29
+ end
30
+ end
31
+
32
+ desc 'render HAML', 'Benchmark rendering'
33
+ def render(file)
34
+ puts "#{?= * 49}\n Rendering: #{file}\n#{?= * 49}"
35
+ haml = File.read(file)
36
+ puts haml + "\n" if options[:show_template]
37
+ object = Object.new
38
+ ruby_file = file.gsub(/\.haml\z/, '.rb')
39
+ if File.exist?(ruby_file)
40
+ object.instance_eval(File.read(ruby_file))
41
+ end
42
+
43
+ object.instance_eval "def haml; #{Haml::Engine.new.call(haml)}; end"
44
+
45
+ Benchmark.ips do |x|
46
+ x.report("haml v#{Haml::VERSION}") { object.haml }
47
+ x.compare!
48
+ end
49
+ end
50
+
51
+ desc 'code HAML', 'Show compiled code'
52
+ def code(file)
53
+ haml = File.read(file)
54
+ puts "\n#{?= * 49}\n Haml Source: #{file}\n#{?= * 49}"
55
+ puts Haml::Engine.new.call(haml)
56
+ end
57
+
58
+ private
59
+
60
+ def method_missing(*args)
61
+ return super if args.length > 1
62
+ render(args.first.to_s)
63
+ end
64
+ end
65
+
66
+ Bench.start
data/bin/console ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'hamlit'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ require 'pry'
11
+ Pry.start
data/bin/ruby ADDED
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+
3
+ bundle exec ruby -Ilib:test -rtest_helper $@
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
data/bin/stackprof ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'hamlit'
5
+ require 'stackprof'
6
+
7
+ def open_flamegraph(report)
8
+ temp = `mktemp /tmp/stackflame-XXXXXXXX`.strip
9
+ data_path = "#{temp}.js"
10
+ system("mv #{temp} #{data_path}")
11
+
12
+ File.open(data_path, 'w') do |f|
13
+ report.print_flamegraph(f)
14
+ end
15
+
16
+ viewer_path = File.join(`bundle show stackprof`.strip, 'lib/stackprof/flamegraph/viewer.html')
17
+ url = "file://#{viewer_path}?data=#{data_path}"
18
+ system(%Q[osascript -e 'open location "#{url}"'])
19
+ end
20
+
21
+ haml = File.read(ARGV.first)
22
+ StackProf.start(mode: :wall, interval: 1, raw: false)
23
+ Hamlit::Engine.new.call(haml)
24
+ StackProf.stop
25
+
26
+ report = StackProf::Report.new(StackProf.results)
27
+ report.print_text(false)
data/bin/test ADDED
@@ -0,0 +1,24 @@
1
+ #!/bin/bash
2
+
3
+ VERSIONS=(
4
+ 2.1.10
5
+ 2.2.5
6
+ 2.3.1
7
+ )
8
+
9
+ set -e
10
+ trap 'echo "${VERSIONS[2]}" > .ruby-version' 0
11
+
12
+ function test_with() {
13
+ version=$1
14
+ rbenv local $version
15
+ if ! bundle check > /dev/null; then
16
+ bundle install
17
+ fi
18
+ ruby -v
19
+ bundle exec rake test
20
+ }
21
+
22
+ for version in ${VERSIONS[@]}; do
23
+ test_with $version
24
+ done
data/exe/haml ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.expand_path('../lib', __dir__)
4
+ require 'haml/cli'
5
+
6
+ Haml::CLI.start(ARGV)