haml 5.1.2 → 6.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +3 -0
  3. data/.github/workflows/test.yml +35 -0
  4. data/.gitignore +16 -15
  5. data/.yardopts +0 -3
  6. data/CHANGELOG.md +137 -0
  7. data/Gemfile +18 -14
  8. data/MIT-LICENSE +1 -1
  9. data/README.md +5 -6
  10. data/REFERENCE.md +103 -150
  11. data/Rakefile +48 -88
  12. data/bin/bench +66 -0
  13. data/bin/console +11 -0
  14. data/bin/ruby +3 -0
  15. data/bin/setup +7 -0
  16. data/bin/stackprof +27 -0
  17. data/bin/test +24 -0
  18. data/exe/haml +6 -0
  19. data/ext/haml/extconf.rb +10 -0
  20. data/ext/haml/haml.c +537 -0
  21. data/ext/haml/hescape.c +108 -0
  22. data/ext/haml/hescape.h +20 -0
  23. data/haml.gemspec +39 -36
  24. data/lib/haml/ambles.rb +20 -0
  25. data/lib/haml/attribute_builder.rb +139 -129
  26. data/lib/haml/attribute_compiler.rb +86 -182
  27. data/lib/haml/attribute_parser.rb +92 -126
  28. data/lib/haml/cli.rb +154 -0
  29. data/lib/haml/compiler/children_compiler.rb +155 -0
  30. data/lib/haml/compiler/comment_compiler.rb +51 -0
  31. data/lib/haml/compiler/doctype_compiler.rb +46 -0
  32. data/lib/haml/compiler/script_compiler.rb +114 -0
  33. data/lib/haml/compiler/silent_script_compiler.rb +24 -0
  34. data/lib/haml/compiler/tag_compiler.rb +76 -0
  35. data/lib/haml/compiler.rb +63 -296
  36. data/lib/haml/dynamic_merger.rb +67 -0
  37. data/lib/haml/engine.rb +48 -227
  38. data/lib/haml/error.rb +5 -4
  39. data/lib/haml/escape.rb +13 -0
  40. data/lib/haml/escape_any.rb +21 -0
  41. data/lib/haml/filters/base.rb +12 -0
  42. data/lib/haml/filters/cdata.rb +20 -0
  43. data/lib/haml/filters/coffee.rb +17 -0
  44. data/lib/haml/filters/css.rb +33 -0
  45. data/lib/haml/filters/erb.rb +10 -0
  46. data/lib/haml/filters/escaped.rb +22 -0
  47. data/lib/haml/filters/javascript.rb +33 -0
  48. data/lib/haml/filters/less.rb +20 -0
  49. data/lib/haml/filters/markdown.rb +11 -0
  50. data/lib/haml/filters/plain.rb +29 -0
  51. data/lib/haml/filters/preserve.rb +22 -0
  52. data/lib/haml/filters/ruby.rb +10 -0
  53. data/lib/haml/filters/sass.rb +15 -0
  54. data/lib/haml/filters/scss.rb +15 -0
  55. data/lib/haml/filters/text_base.rb +25 -0
  56. data/lib/haml/filters/tilt_base.rb +59 -0
  57. data/lib/haml/filters.rb +54 -378
  58. data/lib/haml/force_escape.rb +29 -0
  59. data/lib/haml/helpers.rb +3 -691
  60. data/lib/haml/html.rb +22 -0
  61. data/lib/haml/identity.rb +13 -0
  62. data/lib/haml/object_ref.rb +35 -0
  63. data/lib/haml/parser.rb +189 -26
  64. data/lib/haml/rails_helpers.rb +53 -0
  65. data/lib/haml/rails_template.rb +57 -0
  66. data/lib/haml/railtie.rb +3 -41
  67. data/lib/haml/ruby_expression.rb +32 -0
  68. data/lib/haml/string_splitter.rb +140 -0
  69. data/lib/haml/template.rb +15 -34
  70. data/lib/haml/temple_line_counter.rb +2 -1
  71. data/lib/haml/util.rb +19 -16
  72. data/lib/haml/version.rb +1 -2
  73. data/lib/haml/whitespace.rb +8 -0
  74. data/lib/haml.rb +8 -20
  75. metadata +222 -52
  76. data/.gitmodules +0 -3
  77. data/.travis.yml +0 -97
  78. data/TODO +0 -24
  79. data/benchmark.rb +0 -70
  80. data/bin/haml +0 -9
  81. data/lib/haml/.gitattributes +0 -1
  82. data/lib/haml/buffer.rb +0 -238
  83. data/lib/haml/escapable.rb +0 -50
  84. data/lib/haml/exec.rb +0 -347
  85. data/lib/haml/generator.rb +0 -42
  86. data/lib/haml/helpers/action_view_extensions.rb +0 -60
  87. data/lib/haml/helpers/action_view_mods.rb +0 -132
  88. data/lib/haml/helpers/action_view_xss_mods.rb +0 -60
  89. data/lib/haml/helpers/safe_erubi_template.rb +0 -20
  90. data/lib/haml/helpers/safe_erubis_template.rb +0 -33
  91. data/lib/haml/helpers/xss_mods.rb +0 -111
  92. data/lib/haml/options.rb +0 -273
  93. data/lib/haml/plugin.rb +0 -37
  94. data/lib/haml/sass_rails_filter.rb +0 -47
  95. data/lib/haml/template/options.rb +0 -27
  96. data/lib/haml/temple_engine.rb +0 -123
  97. data/yard/default/.gitignore +0 -1
  98. data/yard/default/fulldoc/html/css/common.sass +0 -15
  99. 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,43 +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
- # config/initializers/haml.rb
111
- Haml::Template.options[:format] = :html5
91
+ ```ruby
92
+ # config/initializers/haml.rb
93
+ Haml::RailsTemplate.set_options(escape_html: false)
94
+ ```
112
95
 
113
- Outside Rails, you can set them by configuring them globally in
114
- Haml::Options.defaults:
96
+ Outside Rails, you can set them by configuring them globally in `Haml::Template.options`:
115
97
 
116
- Haml::Options.defaults[:format] = :html5
98
+ ```ruby
99
+ Haml::Template.options[:escape_html] = false
100
+ ```
117
101
 
118
102
  In sinatra specifically, you can set them in global config with:
119
103
  ```ruby
120
- set :haml, { escape_html: true }
104
+ set :haml, { escape_html: false }
121
105
  ```
122
106
 
123
- Finally, you can also set them by passing an options hash to
124
- {Haml::Engine#initialize}. For the complete list of available options, please
125
- see {Haml::Options}.
126
-
127
- ### Encodings
128
-
129
- Haml supports the same sorts of
130
- encoding-declaration comments that Ruby does. Although both Ruby and Haml
131
- support several different styles, the easiest it just to add `-# coding:
132
- encoding-name` at the beginning of the Haml template (it must come before all
133
- other lines). This will tell Haml that the template is encoded using the named
134
- encoding.
135
-
136
- By default, the HTML generated by Haml has the same encoding as the Haml
137
- template. However, if `Encoding.default_internal` is set, Haml will attempt to
138
- use that instead. In addition, the {Haml::Options#encoding `:encoding` option}
139
- can be used to specify an output encoding manually.
140
-
141
- Note that, like Ruby, Haml does not support templates encoded in UTF-16 or
142
- UTF-32, since these encodings are not compatible with ASCII. It is possible to
143
- 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`.
144
109
 
145
110
  ## Plain Text
146
111
 
@@ -228,15 +193,19 @@ is compiled to:
228
193
  <html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'></html>
229
194
 
230
195
  Attribute hashes can also be stretched out over multiple lines to accommodate
231
- many attributes. However, newlines may only be placed immediately after commas.
232
- For example:
196
+ many attributes.
233
197
 
234
- %script{:type => "text/javascript",
235
- :src => "javascripts/script_#{2 + 7}"}
198
+ %script{
199
+ "type": text/javascript",
200
+ "src": javascripts/script_#{2 + 7}",
201
+ "data": {
202
+ "controller": "reporter",
203
+ },
204
+ }
236
205
 
237
206
  is compiled to:
238
207
 
239
- <script src='javascripts/script_9' type='text/javascript'></script>
208
+ <script src='javascripts/script_9' type='text/javascript' data-controller='reporter'></script>
240
209
 
241
210
  #### `:class` and `:id` Attributes {#class-and-id-attributes}
242
211
 
@@ -314,49 +283,6 @@ Haml also supports Ruby's new hash syntax:
314
283
 
315
284
  %a{title: @title, href: href} Stuff
316
285
 
317
- #### Attribute Methods
318
-
319
- A Ruby method call that returns a hash can be substituted for the hash contents.
320
- For example, {Haml::Helpers} defines the following method:
321
-
322
- def html_attrs(lang = 'en-US')
323
- {:xmlns => "http://www.w3.org/1999/xhtml", 'xml:lang' => lang, :lang => lang}
324
- end
325
-
326
- This can then be used in Haml, like so:
327
-
328
- %html{html_attrs('fr-fr')}
329
-
330
- This is compiled to:
331
-
332
- <html lang='fr-fr' xml:lang='fr-fr' xmlns='http://www.w3.org/1999/xhtml'>
333
- </html>
334
-
335
- You can use as many such attribute methods as you want by separating them with
336
- commas, like a Ruby argument list. All the hashes will be merged together, from
337
- left to right. For example, if you defined
338
-
339
- def hash1
340
- {:bread => 'white', :filling => 'peanut butter and jelly'}
341
- end
342
-
343
- def hash2
344
- {:bread => 'whole wheat'}
345
- end
346
-
347
- then
348
-
349
- %sandwich{hash1, hash2, :delicious => 'true'}/
350
-
351
- would compile to:
352
-
353
- <sandwich bread='whole wheat' delicious='true' filling='peanut butter and jelly' />
354
-
355
- Note that the Haml attributes list has the same syntax as a Ruby method call.
356
- This means that any attribute methods must come before the hash literal.
357
-
358
- Attribute methods aren't supported for HTML-style attributes.
359
-
360
286
  #### Boolean Attributes
361
287
 
362
288
  Some attributes, such as "checked" for `input` tags or "selected" for `option`
@@ -393,24 +319,38 @@ or using `true` and `false`:
393
319
 
394
320
  %input(selected=true)
395
321
 
322
+ This feature works only for attributes that are included in
323
+ [`Haml::AttributeBuilder::BOOLEAN_ATTRIBUTES`](lib/haml/attribute_builder.rb),
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
+
396
337
  <!-- The title to the next section (Prefixed Attributes) has changed. This
397
338
  <a> tag is so old links to here still work. -->
398
339
  <a id="html5_custom_data_attributes" style="border:0;"></a>
399
340
 
400
- #### Prefixed Attributes
341
+ #### Data Attributes
401
342
 
402
343
  HTML5 allows for adding
403
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)
404
345
  to elements using attribute names beginning with `data-`. The
405
346
  [Accessible Rich Internet Applications](http://www.w3.org/WAI/intro/aria)
406
- specification makes use of attributes beginning with `aria-`. There are also
407
- frameworks that use non-standard attributes with a common prefix.
347
+ specification makes use of attributes beginning with `aria-`.
408
348
 
409
349
  Haml can help generate collections of attributes that share a prefix like
410
- these. Any entry in an attribute hash that has a Hash as its value is expanded
411
- into a series of attributes, one for each key/value pair in the hash, with the
412
- attribute name formed by joining the “parent” key name to the key name with a
413
- 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`.
414
354
 
415
355
  For example:
416
356
 
@@ -517,6 +457,24 @@ and is compiled to:
517
457
  </div>
518
458
  </div>
519
459
 
460
+ #### Class Name Merging and Ordering
461
+
462
+ Class names are ordered in the following way:
463
+
464
+ 1) Tag identifiers in order (aka, ".alert.me" => "alert me")
465
+ 2) Classes appearing in HTML-style attributes
466
+ 3) Classes appearing in Hash-style attributes
467
+
468
+ For instance, this is a complicated and unintuitive test case illustrating the ordering
469
+
470
+ .foo.moo{:class => ['bar', 'alpha']}(class='baz')
471
+
472
+ The resulting HTML would be as follows:
473
+
474
+ <div class='foo moo baz bar alpha'></div>
475
+
476
+ *Versions of Haml prior to 5.0 would alphabetically sort class names.*
477
+
520
478
  ### Empty (void) Tags: `/`
521
479
 
522
480
  The forward slash character, when placed at the end of a tag definition, causes
@@ -853,7 +811,7 @@ is compiled to:
853
811
 
854
812
  ## Ruby Evaluation
855
813
 
856
- ### Inserting Ruby: `=`
814
+ ### Inserting Ruby: `=` {#inserting_ruby}
857
815
 
858
816
  The equals character is followed by Ruby code. This code is evaluated and the
859
817
  output is inserted into the document. For example:
@@ -964,7 +922,7 @@ is compiled to:
964
922
 
965
923
  ### Whitespace Preservation: `~` {#tilde}
966
924
 
967
- `~` works just like `=`, except that it runs {Haml::Helpers#find\_and\_preserve}
925
+ `~` works just like `=`, except that it runs {Haml::Helpers.preserve}
968
926
  on its input. For example,
969
927
 
970
928
  ~ "Foo\n<pre>Bar\nBaz</pre>"
@@ -1125,9 +1083,6 @@ is compiled to
1125
1083
  <p>I <strong>really</strong> prefer <em>raspberry</em> jam.</p>
1126
1084
  </div>
1127
1085
 
1128
- Note that `#{}` interpolation within filters is HTML-escaped if you specify true to
1129
- {Haml::Options#escape_filter_interpolations `:escape_filter_interpolations`} option.
1130
-
1131
1086
  The functionality of some filters such as Markdown can be provided by many
1132
1087
  different libraries. Usually you don't have to worry about this - you can just
1133
1088
  load the gem of your choice and Haml will automatically use it.
@@ -1242,43 +1197,48 @@ default. This filter is implemented using Tilt.
1242
1197
 
1243
1198
  ### Custom Filters
1244
1199
 
1245
- You can also define your own filters. See {Haml::Filters} for details.
1246
-
1247
- ## Helper Methods {#helper-methods}
1248
-
1249
- Sometimes you need to manipulate whitespace in a more precise fashion than what
1250
- the whitespace removal methods allow. There are a few helper methods that are
1251
- useful when dealing with inline content. All these methods take a Haml block to
1252
- modify.
1253
-
1254
- ### surround {#surround}
1255
-
1256
- Surrounds a Haml block with text. Expects 1 or 2 string arguments used to
1257
- surround the Haml block. If a second argument is not provided, the first
1258
- argument is used as the second.
1200
+ You can also define your own filters.
1201
+ `Haml::Filters::YourCustomFilter#compile` should return
1202
+ [a Temple expression](https://github.com/judofyr/temple/blob/master/EXPRESSIONS.md).
1259
1203
 
1260
- = surround "(", ")" do
1261
- = link_to "learn more", "#"
1204
+ The simplest example of a filter might be something like:
1262
1205
 
1263
- ### precede {#precede}
1206
+ ```ruby
1207
+ class HelloFilter < Haml::Filters::Base
1208
+ def compile(_node)
1209
+ [:static, "hello world"]
1210
+ end
1211
+ end
1264
1212
 
1265
- Prepends a Haml block with text. Expects 1 argument.
1213
+ Haml::Filters.registered[:hello] ||= HelloFilter
1214
+ ```
1266
1215
 
1267
- = precede "*" do
1268
- %span Required
1216
+ A more complex complex example
1269
1217
 
1270
- ### succeed {#succeed}
1218
+ ```ruby
1219
+ class BetterFilter < Haml::Filters::Base
1220
+ def compile(node)
1221
+ temple = [:multi]
1222
+ temple << [:static, "hello "]
1223
+ temple << compile_text(node.value[:text])
1224
+ temple << [:static, " world"]
1225
+ temple
1226
+ end
1227
+
1228
+ private
1229
+ def compile_text(text)
1230
+ if ::Haml::Util.contains_interpolation?(text)
1231
+ [:dynamic, ::Haml::Util.unescape_interpolation(text)]
1232
+ else
1233
+ [:static, text]
1234
+ end
1235
+ end
1236
+ end
1271
1237
 
1272
- Appends a Haml block with text. Expects 1 argument.
1238
+ Haml::Filters.registered[:better] ||= BetterFilter
1239
+ ```
1273
1240
 
1274
- Begin by
1275
- = succeed "," do
1276
- = link_to "filling out your profile", "#"
1277
- = succeed "," do
1278
- = link_to "adding a bio", "#"
1279
- and
1280
- = succeed "." do
1281
- = link_to "inviting friends", "#"
1241
+ See {Haml::Filters} for examples.
1282
1242
 
1283
1243
  ## Multiline: `|` {#multiline}
1284
1244
 
@@ -1323,7 +1283,7 @@ that just need a lot of template information.
1323
1283
  So data structures and functions that require lots of arguments
1324
1284
  can be wrapped over multiple lines,
1325
1285
  as long as each line but the last ends in a comma
1326
- (see [Inserting Ruby](#inserting_ruby_)).
1286
+ (see [Inserting Ruby](#inserting_ruby)).
1327
1287
 
1328
1288
  ## Whitespace Preservation
1329
1289
 
@@ -1338,14 +1298,7 @@ Haml won't try to re-format the indentation.
1338
1298
  Literal `textarea` and `pre` tags automatically preserve content given through
1339
1299
  `=`. Dynamically-generated `textarea`s and `pre`s can't be preserved
1340
1300
  automatically, and so should be passed through
1341
- {Haml::Helpers#find\_and\_preserve} or the [`~` command](#tilde), which has the
1301
+ {Haml::Helpers.preserve} or the [`~` command](#tilde), which has the
1342
1302
  same effect.
1343
1303
 
1344
1304
  Blocks of literal text can be preserved using the [`:preserve` filter](#preserve-filter).
1345
-
1346
- ## Helpers
1347
-
1348
- Haml offers a bunch of helpers that are useful for doing stuff like preserving
1349
- whitespace, creating nicely indented output for user-defined helpers, and other
1350
- useful things. The helpers are all documented in the {Haml::Helpers} and
1351
- {Haml::Helpers::ActionViewExtensions} modules.
data/Rakefile CHANGED
@@ -1,43 +1,57 @@
1
- require "rake/clean"
2
- require "rake/testtask"
3
- require "bundler/gem_tasks"
4
-
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
- Rake::TestTask.new do |t|
16
- t.libs << 'test'
17
- t.test_files = Dir['test/*_test.rb'] + Dir['test/haml-spec/*_test.rb'] - isolated_test.file_list
18
- t.warning = true
19
- t.verbose = true
1
+ require 'bundler/gem_tasks'
2
+
3
+ #
4
+ # Prepend DevKit into compilation phase
5
+ #
6
+ if Gem.win_platform?
7
+ desc 'Activates DevKit'
8
+ task :devkit do
9
+ begin
10
+ require 'devkit'
11
+ rescue LoadError
12
+ abort 'Failed to load DevKit required for compilation'
13
+ end
14
+ end
15
+ task compile: :devkit
20
16
  end
21
17
 
22
- CLEAN.replace %w(pkg doc coverage .yardoc test/haml vendor)
18
+ require 'rake/testtask'
19
+ if /java/ === RUBY_PLATFORM
20
+ # require 'rake/javaextensiontask'
21
+ # Rake::JavaExtensionTask.new(:haml) do |ext|
22
+ # ext.ext_dir = 'ext/java'
23
+ # ext.lib_dir = 'lib/haml'
24
+ # end
23
25
 
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 :set_coverage_env do
30
- ENV["COVERAGE"] = "true"
26
+ task :compile do
27
+ # dummy for now
28
+ end
29
+ else
30
+ require 'rake/extensiontask'
31
+ Rake::ExtensionTask.new(:haml) do |ext|
32
+ ext.lib_dir = 'lib/haml'
33
+ end
31
34
  end
32
35
 
33
- desc "Run Simplecov"
34
- task :coverage => [:set_coverage_env, :test]
36
+ Dir['benchmark/*.rake'].each { |b| import(b) }
35
37
 
36
- task :submodules do
37
- if File.exist?(File.dirname(__FILE__) + "/.git")
38
- sh %{git submodule sync}
39
- sh %{git submodule update --init --recursive}
38
+ Rake::TestTask.new do |t|
39
+ t.libs << 'lib' << 'test'
40
+ files = Dir['test/haml/**/*_test.rb']
41
+ t.ruby_opts = %w[-rtest_helper]
42
+ t.test_files = files
43
+ t.verbose = true
44
+ end
45
+ task test: :compile
46
+
47
+ desc 'bench task for CI'
48
+ task bench: :compile do
49
+ if ENV['SLIM_BENCH'] == '1'
50
+ cmd = %w[bundle exec ruby benchmark/slim/run-benchmarks.rb]
51
+ else
52
+ cmd = ['bin/bench', 'bench', ('-c' if ENV['COMPILE'] == '1'), *ENV['TEMPLATE'].split(',')].compact
40
53
  end
54
+ exit system(*cmd)
41
55
  end
42
56
 
43
57
  namespace :doc do
@@ -65,58 +79,4 @@ task(:doc => 'doc:sass') {sh "yard"}
65
79
  desc "Generate documentation incrementally"
66
80
  task(:redoc) {sh "yard -c"}
67
81
 
68
- desc <<END
69
- Profile Haml.
70
- TIMES=n sets the number of runs. Defaults to 1000.
71
- FILE=str sets the file to profile. Defaults to 'standard'
72
- OUTPUT=str sets the ruby-prof output format.
73
- Can be Flat, CallInfo, or Graph. Defaults to Flat. Defaults to Flat.
74
- END
75
- task :profile do
76
- times = (ENV['TIMES'] || '1000').to_i
77
- file = ENV['FILE'] || 'test/templates/standard.haml'
78
-
79
- require 'bundler/setup'
80
- require 'ruby-prof'
81
- require 'haml'
82
- file = File.read(File.expand_path("../#{file}", __FILE__))
83
- obj = Object.new
84
- Haml::Engine.new(file).def_method(obj, :render)
85
- result = RubyProf.profile { times.times { obj.render } }
86
-
87
- RubyProf.const_get("#{(ENV['OUTPUT'] || 'Flat').capitalize}Printer").new(result).print
88
- end
89
-
90
- def gemfiles
91
- @gemfiles ||= Dir[File.dirname(__FILE__) + '/test/gemfiles/Gemfile.*'].reject {|f| f =~ /\.lock$/}
92
- end
93
-
94
- def with_each_gemfile
95
- gemfiles.each do |gemfile|
96
- Bundler.with_clean_env do
97
- puts "Using gemfile: #{gemfile}"
98
- ENV['BUNDLE_GEMFILE'] = gemfile
99
- yield
100
- end
101
- end
102
- end
103
-
104
- namespace :test do
105
- namespace :bundles do
106
- desc "Install all dependencies necessary to test Haml."
107
- task :install do
108
- with_each_gemfile {sh "bundle"}
109
- end
110
-
111
- desc "Update all dependencies for testing Haml."
112
- task :update do
113
- with_each_gemfile {sh "bundle update"}
114
- end
115
- end
116
-
117
- desc "Test all supported versions of rails. This takes a while."
118
- task :rails_compatibility => 'test:bundles:install' do
119
- with_each_gemfile {sh "bundle exec rake test"}
120
- end
121
- task :rc => :rails_compatibility
122
- end
82
+ task default: %w[compile 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)