haml 6.0.1 → 6.0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 909d5636fba736ef06747221b4d0ff34a8c5b850f2c8d4cc60ac27843e914e94
4
- data.tar.gz: 478fd2cce0e05e386690aa83fa41132da006cb02437ec43a0b4882842a2e973c
3
+ metadata.gz: ec341f61274ad9cac37bc7df1c3ca31cfd7cfcb5d049ab9d2d2b505d7d314de9
4
+ data.tar.gz: 0a3e2dc6d6e03f586d51980e7db967b9626a1ec4563352d195e472756327b734
5
5
  SHA512:
6
- metadata.gz: 268bfdc33ba76950ab553692c5ff1c45b84a3f3b4185248a19c6a3a74f4b47cd46527d279ed3782f9b7fd6bba6be889a531b7e6c133a4f00ac7e3e06d61a464c
7
- data.tar.gz: 1b4f559abe65e3c39627d87b6cc2da894ca67514f62d702ff0920d9d974dda49d4ab7b49e465157622b31a9c3ad5b1925e5e4aa2b1360640d784a7a6f537178a
6
+ metadata.gz: 529e8c001b4dae92210e8d74f3027367ad826b1f963dec92f6680378ed1b85ddd7285de0dc99e188f6557b1e439fb4157120578af68ef00292aa5a8de11e1e4f
7
+ data.tar.gz: a1871dcc07d3b0bbd45e30aaab1f0b7d043af90e276fbf163a1645ac72c7891f9d163a928857d2333f23e36955bde20aa1f1b90f373ba0d1ee6e6b285cca33f9
data/.yardopts ADDED
@@ -0,0 +1,19 @@
1
+ --charset utf-8
2
+ --readme README.md
3
+ --markup markdown
4
+ --markup-provider kramdown
5
+ --template-path yard
6
+ --default-return ""
7
+ --title "Haml Documentation"
8
+ --query 'object.type != :classvariable'
9
+ --query 'object.type != :constant || @api && @api.text == "public"'
10
+ --exclude lib/haml/railtie.rb
11
+ --hide-void-return
12
+ --protected
13
+ --no-private
14
+ --no-highlight
15
+ -
16
+ FAQ.md
17
+ CHANGELOG.md
18
+ REFERENCE.md
19
+ MIT-LICENSE
data/CHANGELOG.md CHANGED
@@ -1,5 +1,45 @@
1
1
  # Haml Changelog
2
2
 
3
+ ## 6.0.7
4
+
5
+ * `Haml::Engine` and `Haml::Template` use StringBuffer instead of ArrayBuffer
6
+ * It seems more performant in many cases with recent Ruby versions.
7
+ * `Haml::RailsTemplate` is not affected.
8
+
9
+ ## 6.0.6
10
+
11
+ * Prevent CRuby from accidentally using the Ruby implementation fallback
12
+ * Reversing what v6.0.3 and v6.0.4 did, but still supporting Wasm.
13
+
14
+ ## 6.0.5
15
+
16
+ * Resurrect `#haml_object_ref` support in an object reference [#1097](https://github.com/haml/haml/issues/1097)
17
+ * This was removed in 6.0.0, and added back in this version.
18
+ * Stop warning `remove_whitespace: true` option.
19
+
20
+ ## 6.0.4
21
+
22
+ Released on October 2, 2022
23
+ ([diff](https://github.com/haml/haml/compare/v6.0.3...v6.0.4)).
24
+
25
+ * Fix a parse failure of `%` in attributes [#1096](https://github.com/haml/haml/issues/1096)
26
+ * Add another fallback from C to Ruby for Wasm.
27
+
28
+ ## 6.0.3
29
+
30
+ Released on September 28, 2022
31
+ ([diff](https://github.com/haml/haml/compare/v6.0.2...v6.0.3)).
32
+
33
+ * For Wasm, fallback to Ruby when C extension is not available.
34
+
35
+ ## 6.0.2
36
+
37
+ Released on September 28, 2022
38
+ ([diff](https://github.com/haml/haml/compare/v6.0.1...v6.0.2)).
39
+
40
+ * Unescape HTML-safe arguments for `surround`, `succeed`, and `precede` on Rails
41
+ [#1088](https://github.com/haml/haml/issues/1088)
42
+
3
43
  ## 6.0.1
4
44
 
5
45
  Released on September 23, 2022
@@ -17,7 +57,19 @@ Released on September 21, 2022
17
57
  * Haml 6 is about 1.7x faster than Haml 5 in [this benchmark](benchmark/slim/run-benchmarks.rb).
18
58
  * The parser is kept as is, but everything else is replaced.
19
59
  * The `haml` CLI interface was also replaced.
20
- * All Haml helpers except for `preserve` are removed.
60
+ * The interface of `Haml::Engine` is changed. `Haml::Template` is most likely what you need now.
61
+ * Most Haml helpers are removed.
62
+ * Rails:
63
+ * Kept: `find_and_reserve`, `preserve`, `surround`, `precede`, `succeed`, `capture_haml`
64
+ * Removed: `block_is_haml?`, `flatten`, `haml_concat`, `haml_indent`, `haml_tag`, `haml_tag_if`, `html_attrs`,
65
+ `html_escape`, `init_haml_helpers`, `is_haml?`, `list_of`, `non_haml`, `tab_down`, `tab_up`, `with_tabs`
66
+ * Tilt:
67
+ * Kept: `preserve`
68
+ * Removed: `block_is_haml?`, `capture_haml`, `escape_once`, `find_and_preserve`, `flatten`, `haml_concat`,
69
+ `haml_indent`, `haml_tag`, `haml_tag_if`, `html_attrs`, `html_escape`, `init_haml_helpers`, `is_haml?`,
70
+ `list_of`, `non_haml`, `precede`, `succeed`, `surround`, `tab_down`, `tab_up`, `with_tabs`
71
+ * Only the attributes in [`Haml::AttributeBuilder::BOOLEAN_ATTRIBUTES`](lib/haml/attribute_builder.rb)
72
+ are handled as boolean attributes.
21
73
  * Some legacy Rails integration is removed.
22
74
 
23
75
  ## 5.2.2
data/README.md CHANGED
@@ -22,7 +22,7 @@ gem install haml
22
22
  After you write some Haml, you can run
23
23
 
24
24
  ~~~sh
25
- haml document.haml
25
+ haml render document.haml
26
26
  ~~~
27
27
 
28
28
  to compile it to HTML. For more information on these commands, check out
@@ -41,8 +41,8 @@ To use Haml with Rails, simply add Haml to your Gemfile and run `bundle`.
41
41
  gem 'haml'
42
42
  ~~~
43
43
 
44
- If you'd like to replace Rails's Erb-based generators with Haml, add
45
- [haml-rails](https://github.com/indirect/haml-rails) to your Gemfile as well.
44
+ If you'd like to replace Rails's ERB-based generators with Haml, add
45
+ [haml-rails](https://github.com/haml/haml-rails) to your Gemfile as well.
46
46
 
47
47
  ## Formatting
48
48
 
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
 
@@ -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,6 +319,21 @@ 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`](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
+
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>
@@ -993,7 +923,7 @@ is compiled to:
993
923
 
994
924
  ### Whitespace Preservation: `~` {#tilde}
995
925
 
996
- `~` works just like `=`, except that it runs {Haml::Helpers#find\_and\_preserve}
926
+ `~` works just like `=`, except that it runs {Haml::Helpers.preserve}
997
927
  on its input. For example,
998
928
 
999
929
  ~ "Foo\n<pre>Bar\nBaz</pre>"
@@ -1154,9 +1084,6 @@ is compiled to
1154
1084
  <p>I <strong>really</strong> prefer <em>raspberry</em> jam.</p>
1155
1085
  </div>
1156
1086
 
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
1087
  The functionality of some filters such as Markdown can be provided by many
1161
1088
  different libraries. Usually you don't have to worry about this - you can just
1162
1089
  load the gem of your choice and Haml will automatically use it.
@@ -1271,43 +1198,48 @@ default. This filter is implemented using Tilt.
1271
1198
 
1272
1199
  ### Custom Filters
1273
1200
 
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.
1201
+ You can also define your own filters.
1202
+ `Haml::Filters::YourCustomFilter#compile` should return
1203
+ [a Temple expression](https://github.com/judofyr/temple/blob/master/EXPRESSIONS.md).
1282
1204
 
1283
- ### surround {#surround}
1205
+ The simplest example of a filter might be something like:
1284
1206
 
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.
1288
-
1289
- = surround "(", ")" do
1290
- = link_to "learn more", "#"
1291
-
1292
- ### precede {#precede}
1207
+ ```ruby
1208
+ class HelloFilter < Haml::Filters::Base
1209
+ def compile(_node)
1210
+ [:static, "hello world"]
1211
+ end
1212
+ end
1293
1213
 
1294
- Prepends a Haml block with text. Expects 1 argument.
1214
+ Haml::Filters.registered[:hello] ||= HelloFilter
1215
+ ```
1295
1216
 
1296
- = precede "*" do
1297
- %span Required
1217
+ A more complex complex example
1298
1218
 
1299
- ### succeed {#succeed}
1219
+ ```ruby
1220
+ class BetterFilter < Haml::Filters::Base
1221
+ def compile(node)
1222
+ temple = [:multi]
1223
+ temple << [:static, "hello "]
1224
+ temple << compile_text(node.value[:text])
1225
+ temple << [:static, " world"]
1226
+ temple
1227
+ end
1228
+
1229
+ private
1230
+ def compile_text(text)
1231
+ if ::Haml::Util.contains_interpolation?(text)
1232
+ [:dynamic, ::Haml::Util.unescape_interpolation(text)]
1233
+ else
1234
+ [:static, text]
1235
+ end
1236
+ end
1237
+ end
1300
1238
 
1301
- Appends a Haml block with text. Expects 1 argument.
1239
+ Haml::Filters.registered[:better] ||= BetterFilter
1240
+ ```
1302
1241
 
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", "#"
1242
+ See {Haml::Filters} for examples.
1311
1243
 
1312
1244
  ## Multiline: `|` {#multiline}
1313
1245
 
@@ -1367,14 +1299,7 @@ Haml won't try to re-format the indentation.
1367
1299
  Literal `textarea` and `pre` tags automatically preserve content given through
1368
1300
  `=`. Dynamically-generated `textarea`s and `pre`s can't be preserved
1369
1301
  automatically, and so should be passed through
1370
- {Haml::Helpers#find\_and\_preserve} or the [`~` command](#tilde), which has the
1302
+ {Haml::Helpers.preserve} or the [`~` command](#tilde), which has the
1371
1303
  same effect.
1372
1304
 
1373
1305
  Blocks of literal text can be preserved using the [`:preserve` filter](#preserve-filter).
1374
-
1375
- ## Helpers
1376
-
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.
data/Rakefile CHANGED
@@ -35,72 +35,14 @@ end
35
35
 
36
36
  Dir['benchmark/*.rake'].each { |b| import(b) }
37
37
 
38
- namespace :haml do
39
- Rake::TestTask.new do |t|
40
- t.libs << 'lib' << 'test'
41
- files = Dir['test/haml/*_test.rb']
42
- files << 'test/haml/haml-spec/*_test.rb'
43
- t.ruby_opts = %w[-rtest_helper]
44
- t.test_files = files
45
- t.verbose = true
46
- end
47
- end
48
-
49
- namespace :hamlit do
50
- Rake::TestTask.new do |t|
51
- t.libs << 'lib' << 'test'
52
- t.ruby_opts = %w[-rtest_helper]
53
- t.test_files = Dir['test/hamlit/**/*_test.rb']
54
- t.verbose = true
55
- end
56
- end
57
-
58
- namespace :test do
59
- Rake::TestTask.new(:all) do |t|
60
- t.libs << 'lib' << 'test'
61
- files = Dir['test/hamlit/**/*_test.rb']
62
- files += Dir['test/haml/*_test.rb']
63
- files << 'test/haml/haml-spec/*_test.rb'
64
- t.ruby_opts = %w[-rtest_helper]
65
- t.test_files = files
66
- t.verbose = true
67
- end
68
-
69
- Rake::TestTask.new(:spec) do |t|
70
- t.libs << 'lib' << 'test'
71
- t.ruby_opts = %w[-rtest_helper]
72
- t.test_files = %w[test/haml/haml-spec/ugly_test.rb test/haml/haml-spec/pretty_test.rb]
73
- t.verbose = true
74
- end
75
-
76
- Rake::TestTask.new(:engine) do |t|
77
- t.libs << 'lib' << 'test'
78
- t.ruby_opts = %w[-rtest_helper]
79
- t.test_files = %w[test/haml/engine_test.rb]
80
- t.verbose = true
81
- end
82
-
83
- Rake::TestTask.new(:filters) do |t|
84
- t.libs << 'lib' << 'test'
85
- t.ruby_opts = %w[-rtest_helper]
86
- t.test_files = %w[test/haml/filters_test.rb]
87
- t.verbose = true
88
- end
89
-
90
- Rake::TestTask.new(:helper) do |t|
91
- t.libs << 'lib' << 'test'
92
- t.ruby_opts = %w[-rtest_helper]
93
- t.test_files = %w[test/haml/helper_test.rb]
94
- t.verbose = true
95
- end
96
-
97
- Rake::TestTask.new(:template) do |t|
98
- t.libs << 'lib' << 'test'
99
- t.ruby_opts = %w[-rtest_helper]
100
- t.test_files = %w[test/haml/template_test.rb]
101
- t.verbose = true
102
- end
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
103
44
  end
45
+ task test: :compile
104
46
 
105
47
  desc 'bench task for CI'
106
48
  task bench: :compile do
@@ -112,5 +54,29 @@ task bench: :compile do
112
54
  exit system(*cmd)
113
55
  end
114
56
 
115
- task default: %w[compile hamlit:test]
116
- task test: %w[compile test:all]
57
+ namespace :doc do
58
+ task :sass do
59
+ require 'sass'
60
+ Dir["yard/default/**/*.sass"].each do |sass|
61
+ File.open(sass.gsub(/sass$/, 'css'), 'w') do |f|
62
+ f.write(Sass::Engine.new(File.read(sass)).render)
63
+ end
64
+ end
65
+ end
66
+
67
+ desc "List all undocumented methods and classes."
68
+ task :undocumented do
69
+ command = 'yard --list --query '
70
+ command << '"object.docstring.blank? && '
71
+ command << '!(object.type == :method && object.is_alias?)"'
72
+ sh command
73
+ end
74
+ end
75
+
76
+ desc "Generate documentation"
77
+ task(:doc => 'doc:sass') {sh "yard"}
78
+
79
+ desc "Generate documentation incrementally"
80
+ task(:redoc) {sh "yard -c"}
81
+
82
+ task default: %w[compile test]
@@ -9,9 +9,8 @@ module Haml::AttributeBuilder
9
9
  itemscope allowfullscreen default inert sortable
10
10
  truespeed typemustmatch download].freeze
11
11
 
12
- # Java extension is not implemented for JRuby yet.
13
- # TruffleRuby does not implement `rb_ary_sort_bang`, etc.
14
- if /java/ === RUBY_PLATFORM || RUBY_ENGINE == 'truffleruby'
12
+ # For JRuby, TruffleRuby, and Wasm, fallback to Ruby implementation.
13
+ if /java|wasm/ === RUBY_PLATFORM || RUBY_ENGINE == 'truffleruby'
15
14
  class << self
16
15
  def build(escape_attrs, quote, format, boolean_attributes, object_ref, *hashes)
17
16
  hashes << Haml::ObjectRef.parse(object_ref) if object_ref
data/lib/haml/engine.rb CHANGED
@@ -3,6 +3,7 @@ require 'temple'
3
3
  require 'haml/parser'
4
4
  require 'haml/compiler'
5
5
  require 'haml/html'
6
+ require 'haml/string_splitter'
6
7
  require 'haml/escapable'
7
8
  require 'haml/force_escapable'
8
9
  require 'haml/dynamic_merger'
@@ -12,7 +13,7 @@ module Haml
12
13
  class Engine < Temple::Engine
13
14
  define_options(
14
15
  :buffer_class,
15
- generator: Temple::Generators::ArrayBuffer,
16
+ generator: Temple::Generators::StringBuffer,
16
17
  format: :html,
17
18
  attr_quote: "'",
18
19
  escape_html: true,
@@ -22,12 +23,13 @@ module Haml
22
23
  param source track wbr),
23
24
  filename: "",
24
25
  disable_capture: false,
26
+ remove_whitespace: false,
25
27
  )
26
28
 
27
29
  use Parser
28
30
  use Compiler
29
31
  use HTML
30
- filter :StringSplitter
32
+ use StringSplitter
31
33
  filter :StaticAnalyzer
32
34
  use Escapable
33
35
  use ForceEscapable
@@ -6,7 +6,12 @@ module Haml
6
6
  object, prefix = args
7
7
  return {} unless object
8
8
 
9
- suffix = underscore(object.class)
9
+ suffix =
10
+ if object.respond_to?(:haml_object_ref)
11
+ object.haml_object_ref
12
+ else
13
+ underscore(object.class)
14
+ end
10
15
  {
11
16
  'class' => [prefix, suffix].compact.join('_'),
12
17
  'id' => [prefix, suffix, object.id || 'new'].compact.join('_'),
@@ -1,8 +1,7 @@
1
1
  # frozen_string_literal: false
2
2
  require 'haml/helpers'
3
3
 
4
- # Currently this Haml::Helpers depends on
5
- # ActionView internal implementation. (not desired)
4
+ # There are only helpers that depend on ActionView internals.
6
5
  module Haml
7
6
  module RailsHelpers
8
7
  include Helpers
@@ -32,16 +31,19 @@ module Haml
32
31
 
33
32
  def surround(front, back = front, &block)
34
33
  output = capture_haml(&block)
35
-
36
- "#{escape_once(front)}#{output.chomp}#{escape_once(back)}\n".html_safe
34
+ front = escape_once(front) unless front.html_safe?
35
+ back = escape_once(back) unless back.html_safe?
36
+ "#{front}#{output.chomp}#{back}\n".html_safe
37
37
  end
38
38
 
39
39
  def precede(str, &block)
40
- "#{escape_once(str)}#{capture_haml(&block).chomp}\n".html_safe
40
+ str = escape_once(str) unless str.html_safe?
41
+ "#{str}#{capture_haml(&block).chomp}\n".html_safe
41
42
  end
42
43
 
43
44
  def succeed(str, &block)
44
- "#{capture_haml(&block).chomp}#{escape_once(str)}\n".html_safe
45
+ str = escape_once(str) unless str.html_safe?
46
+ "#{capture_haml(&block).chomp}#{str}\n".html_safe
45
47
  end
46
48
 
47
49
  def capture_haml(*args, &block)
@@ -1,19 +1,139 @@
1
1
  # frozen_string_literal: true
2
- require 'ripper'
3
- require 'haml/ruby_expression'
2
+ begin
3
+ require 'ripper'
4
+ rescue LoadError
5
+ end
4
6
 
5
7
  module Haml
6
- module StringSplitter
7
- # `code` param must be valid string literal
8
- def self.compile(code)
9
- unless Ripper.respond_to?(:lex) # truffleruby doesn't have Ripper.lex
10
- return [[:dynamic, code]]
8
+ # Compile [:dynamic, "foo#{bar}"] to [:multi, [:static, 'foo'], [:dynamic, 'bar']]
9
+ class StringSplitter < Temple::Filter
10
+ if defined?(Ripper) && RUBY_VERSION >= "2.0.0" && Ripper.respond_to?(:lex)
11
+ class << self
12
+ # `code` param must be valid string literal
13
+ def compile(code)
14
+ [].tap do |exps|
15
+ tokens = Ripper.lex(code.strip)
16
+ tokens.pop while tokens.last && [:on_comment, :on_sp].include?(tokens.last[1])
17
+
18
+ if tokens.size < 2
19
+ raise(Haml::InternalError, "Expected token size >= 2 but got: #{tokens.size}")
20
+ end
21
+ compile_tokens!(exps, tokens)
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def strip_quotes!(tokens)
28
+ _, type, beg_str = tokens.shift
29
+ if type != :on_tstring_beg
30
+ raise(Haml::InternalError, "Expected :on_tstring_beg but got: #{type}")
31
+ end
32
+
33
+ _, type, end_str = tokens.pop
34
+ if type != :on_tstring_end
35
+ raise(Haml::InternalError, "Expected :on_tstring_end but got: #{type}")
36
+ end
37
+
38
+ [beg_str, end_str]
39
+ end
40
+
41
+ def compile_tokens!(exps, tokens)
42
+ beg_str, end_str = strip_quotes!(tokens)
43
+
44
+ until tokens.empty?
45
+ _, type, str = tokens.shift
46
+
47
+ case type
48
+ when :on_tstring_content
49
+ beg_str, end_str = escape_quotes(beg_str, end_str)
50
+ exps << [:static, eval("#{beg_str}#{str}#{end_str}").to_s]
51
+ when :on_embexpr_beg
52
+ embedded = shift_balanced_embexpr(tokens)
53
+ exps << [:dynamic, embedded] unless embedded.empty?
54
+ end
55
+ end
56
+ end
57
+
58
+ # Some quotes are split-unsafe. Replace such quotes with null characters.
59
+ def escape_quotes(beg_str, end_str)
60
+ case [beg_str[-1], end_str]
61
+ when ['(', ')'], ['[', ']'], ['{', '}']
62
+ [beg_str.sub(/.\z/) { "\0" }, "\0"]
63
+ else
64
+ [beg_str, end_str]
65
+ end
66
+ end
67
+
68
+ def shift_balanced_embexpr(tokens)
69
+ String.new.tap do |embedded|
70
+ embexpr_open = 1
71
+
72
+ until tokens.empty?
73
+ _, type, str = tokens.shift
74
+ case type
75
+ when :on_embexpr_beg
76
+ embexpr_open += 1
77
+ when :on_embexpr_end
78
+ embexpr_open -= 1
79
+ break if embexpr_open == 0
80
+ end
81
+
82
+ embedded << str
83
+ end
84
+ end
85
+ end
11
86
  end
12
87
 
13
- begin
14
- Temple::Filters::StringSplitter.compile(code)
15
- rescue Temple::FilterError => e
16
- raise Haml::InternalError.new(e.message)
88
+ def on_dynamic(code)
89
+ return [:dynamic, code] unless string_literal?(code)
90
+ return [:dynamic, code] if code.include?("\n")
91
+
92
+ temple = [:multi]
93
+ StringSplitter.compile(code).each do |type, content|
94
+ case type
95
+ when :static
96
+ temple << [:static, content]
97
+ when :dynamic
98
+ temple << on_dynamic(content)
99
+ end
100
+ end
101
+ temple
102
+ end
103
+
104
+ private
105
+
106
+ def string_literal?(code)
107
+ return false if SyntaxChecker.syntax_error?(code)
108
+
109
+ type, instructions = Ripper.sexp(code)
110
+ return false if type != :program
111
+ return false if instructions.size > 1
112
+
113
+ type, _ = instructions.first
114
+ type == :string_literal
115
+ end
116
+
117
+ class SyntaxChecker < Ripper
118
+ class ParseError < StandardError; end
119
+
120
+ def self.syntax_error?(code)
121
+ self.new(code).parse
122
+ false
123
+ rescue ParseError
124
+ true
125
+ end
126
+
127
+ private
128
+
129
+ def on_parse_error(*)
130
+ raise ParseError
131
+ end
132
+ end
133
+ else
134
+ # Do nothing if ripper is unavailable
135
+ def call(ast)
136
+ ast
17
137
  end
18
138
  end
19
139
  end
data/lib/haml/util.rb CHANGED
@@ -14,9 +14,8 @@ module Haml
14
14
  module Util
15
15
  extend self
16
16
 
17
- # Java extension is not implemented for JRuby yet.
18
- # TruffleRuby does not implement `rb_ary_sort_bang`, etc.
19
- if /java/ === RUBY_PLATFORM || RUBY_ENGINE == 'truffleruby'
17
+ # For JRuby, TruffleRuby, and Wasm, fallback to Ruby implementation.
18
+ if /java|wasm/ === RUBY_PLATFORM || RUBY_ENGINE == 'truffleruby'
20
19
  require 'cgi/escape'
21
20
 
22
21
  def self.escape_html(html)
data/lib/haml/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Haml
3
- VERSION = '6.0.1'
3
+ VERSION = '6.0.7'
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: haml
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.0.1
4
+ version: 6.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Natalie Weizenbaum
@@ -9,10 +9,10 @@ authors:
9
9
  - Norman Clarke
10
10
  - Akira Matsuda
11
11
  - Takashi Kokubun
12
- autorequire:
12
+ autorequire:
13
13
  bindir: exe
14
14
  cert_chain: []
15
- date: 2022-09-23 00:00:00.000000000 Z
15
+ date: 2022-10-14 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: temple
@@ -265,6 +265,7 @@ files:
265
265
  - ".github/FUNDING.yml"
266
266
  - ".github/workflows/test.yml"
267
267
  - ".gitignore"
268
+ - ".yardopts"
268
269
  - CHANGELOG.md
269
270
  - FAQ.md
270
271
  - Gemfile
@@ -337,7 +338,7 @@ homepage: https://haml.info
337
338
  licenses:
338
339
  - MIT
339
340
  metadata: {}
340
- post_install_message:
341
+ post_install_message:
341
342
  rdoc_options: []
342
343
  require_paths:
343
344
  - lib
@@ -353,7 +354,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
353
354
  version: '0'
354
355
  requirements: []
355
356
  rubygems_version: 3.3.7
356
- signing_key:
357
+ signing_key:
357
358
  specification_version: 4
358
359
  summary: An elegant, structured (X)HTML/XML templating engine.
359
360
  test_files: []