haml 6.0.3 → 6.0.4

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: bee16d977df2038a83ab61bba1ab2b9775cd9ce72883ffd7295a8ccfabaa1b1c
4
- data.tar.gz: a34d4319b5729ef93470bb1fb067b3f334b7b61557d09cef851fcc921dbaffbd
3
+ metadata.gz: 31325683e3bd7edbd6ec19bf99be81bde203ea948059cec704ac260528d6ff8a
4
+ data.tar.gz: 053cbe5fb763691b4fcedd4a8c15649e31dea757a0c7f25366849ae49941e840
5
5
  SHA512:
6
- metadata.gz: 9dea0dfd7f65e4ef17b3c03ce57f0ea1b3211f45ac36174e4253d5407cfa8fcd71185317c91467c22075c18d3475acf1b5b7957b2b0bb62372227d1e014bf9dc
7
- data.tar.gz: 1714b7062bb56f5c298ec07ce864767430b16bbbd132b7f76e8536e4293273f90fe59067a727588860b8cf80ba47f24e204112f530427839b172dc73d2607ae4
6
+ metadata.gz: e480bd4afab654ef3ffdc122cb81c78ca773ca5715310dd876a095491b574722a6b574ae685affb41d5d34eca2465bae737eb3496e3a9bf41df55cdbc74261ac
7
+ data.tar.gz: 9d6c05804e701bca33709a441fdb815f779143a66ad5664f22c8b15583415b198a07044682ed78fb22f653533b26fa5f8ee5d8f96cc4026478ec32796cc99f59
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Haml Changelog
2
2
 
3
+ ## 6.0.4
4
+
5
+ Released on October 2, 2022
6
+ ([diff](https://github.com/haml/haml/compare/v6.0.3...v6.0.4)).
7
+
8
+ * Fix a parse failure of `%` in attributes [#1096](https://github.com/haml/haml/issues/1096)
9
+ * Add another fallback from C to Ruby for Wasm.
10
+
3
11
  ## 6.0.3
4
12
 
5
13
  Released on September 28, 2022
@@ -34,8 +42,15 @@ Released on September 21, 2022
34
42
  * The `haml` CLI interface was also replaced.
35
43
  * The interface of `Haml::Engine` is changed. `Haml::Template` is most likely what you need now.
36
44
  * Most Haml helpers are removed.
37
- * On Rails, only `find_and_reserve`, `preserve`, `surround`, `precede`, `succeed`, and `capture_haml` are left.
38
- * On Tilt, only `preserve` is left.
45
+ * Rails:
46
+ * Kept: `find_and_reserve`, `preserve`, `surround`, `precede`, `succeed`, `capture_haml`
47
+ * Removed: `block_is_haml?`, `flatten`, `haml_concat`, `haml_indent`, `haml_tag`, `haml_tag_if`, `html_attrs`,
48
+ `html_escape`, `init_haml_helpers`, `is_haml?`, `list_of`, `non_haml`, `tab_down`, `tab_up`, `with_tabs`
49
+ * Tilt:
50
+ * Kept: `preserve`
51
+ * Removed: `block_is_haml?`, `capture_haml`, `escape_once`, `find_and_preserve`, `flatten`, `haml_concat`,
52
+ `haml_indent`, `haml_tag`, `haml_tag_if`, `html_attrs`, `html_escape`, `init_haml_helpers`, `is_haml?`,
53
+ `list_of`, `non_haml`, `precede`, `succeed`, `surround`, `tab_down`, `tab_up`, `with_tabs`
39
54
  * Only the attributes in [`Haml::AttributeBuilder::BOOLEAN_ATTRIBUTES`](lib/haml/attribute_builder.rb)
40
55
  are handled as boolean attributes.
41
56
  * Some legacy Rails integration is removed.
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
@@ -137,5 +79,4 @@ task(:doc => 'doc:sass') {sh "yard"}
137
79
  desc "Generate documentation incrementally"
138
80
  task(:redoc) {sh "yard -c"}
139
81
 
140
- task default: %w[compile hamlit:test]
141
- task test: %w[compile test:all]
82
+ task default: %w[compile test]
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'
@@ -27,7 +28,7 @@ module Haml
27
28
  use Parser
28
29
  use Compiler
29
30
  use HTML
30
- filter :StringSplitter
31
+ use StringSplitter
31
32
  filter :StaticAnalyzer
32
33
  use Escapable
33
34
  use ForceEscapable
@@ -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,16 +14,15 @@ 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
+ begin
18
+ require 'haml/haml' # Haml::Util.escape_html
19
+ rescue LoadError
20
+ # For JRuby and Wasm, fallback to Ruby implementation when C extension is not available.
20
21
  require 'cgi/escape'
21
22
 
22
23
  def self.escape_html(html)
23
24
  CGI.escapeHTML(html.to_s)
24
25
  end
25
- else
26
- require 'haml/haml' # Haml::Util.escape_html
27
26
  end
28
27
 
29
28
  # TODO: Remove unescape_interpolation's workaround and get rid of `respond_to?`.
data/lib/haml/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Haml
3
- VERSION = '6.0.3'
3
+ VERSION = '6.0.4'
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.3
4
+ version: 6.0.4
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-28 00:00:00.000000000 Z
15
+ date: 2022-10-03 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: temple
@@ -338,7 +338,7 @@ homepage: https://haml.info
338
338
  licenses:
339
339
  - MIT
340
340
  metadata: {}
341
- post_install_message:
341
+ post_install_message:
342
342
  rdoc_options: []
343
343
  require_paths:
344
344
  - lib
@@ -354,7 +354,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
354
354
  version: '0'
355
355
  requirements: []
356
356
  rubygems_version: 3.3.7
357
- signing_key:
357
+ signing_key:
358
358
  specification_version: 4
359
359
  summary: An elegant, structured (X)HTML/XML templating engine.
360
360
  test_files: []