hamlit 2.11.0 → 2.13.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +30 -0
  3. data/.gitignore +1 -0
  4. data/CHANGELOG.md +43 -1
  5. data/Gemfile +1 -7
  6. data/LICENSE.txt +26 -23
  7. data/README.md +8 -8
  8. data/REFERENCE.md +4 -4
  9. data/benchmark/graph/graph.key +0 -0
  10. data/benchmark/graph/graph.png +0 -0
  11. data/bin/update-haml +125 -0
  12. data/ext/hamlit/hamlit.c +0 -1
  13. data/hamlit.gemspec +1 -1
  14. data/lib/hamlit.rb +6 -4
  15. data/lib/hamlit/attribute_builder.rb +2 -2
  16. data/lib/hamlit/attribute_compiler.rb +3 -3
  17. data/lib/hamlit/compiler/children_compiler.rb +18 -4
  18. data/lib/hamlit/compiler/comment_compiler.rb +1 -0
  19. data/lib/hamlit/filters/escaped.rb +1 -1
  20. data/lib/hamlit/filters/markdown.rb +1 -0
  21. data/lib/hamlit/filters/preserve.rb +1 -1
  22. data/lib/hamlit/filters/text_base.rb +1 -1
  23. data/lib/hamlit/filters/tilt_base.rb +1 -1
  24. data/lib/hamlit/parser.rb +6 -2
  25. data/lib/hamlit/parser/haml_attribute_builder.rb +164 -0
  26. data/lib/hamlit/parser/haml_buffer.rb +20 -130
  27. data/lib/hamlit/parser/haml_compiler.rb +1 -553
  28. data/lib/hamlit/parser/haml_error.rb +29 -25
  29. data/lib/hamlit/parser/haml_escapable.rb +1 -0
  30. data/lib/hamlit/parser/haml_generator.rb +1 -0
  31. data/lib/hamlit/parser/haml_helpers.rb +41 -59
  32. data/lib/hamlit/parser/{haml_xss_mods.rb → haml_helpers/xss_mods.rb} +20 -15
  33. data/lib/hamlit/parser/haml_options.rb +53 -66
  34. data/lib/hamlit/parser/haml_parser.rb +133 -73
  35. data/lib/hamlit/parser/haml_temple_engine.rb +123 -0
  36. data/lib/hamlit/parser/haml_util.rb +10 -40
  37. data/lib/hamlit/rails_template.rb +1 -1
  38. data/lib/hamlit/string_splitter.rb +1 -0
  39. data/lib/hamlit/temple_line_counter.rb +31 -0
  40. data/lib/hamlit/version.rb +1 -1
  41. metadata +15 -9
  42. data/.travis.yml +0 -47
  43. data/lib/hamlit/parser/MIT-LICENSE +0 -20
  44. data/lib/hamlit/parser/README.md +0 -30
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'temple'
4
+ require 'hamlit/parser/haml_escapable'
5
+ require 'hamlit/parser/haml_generator'
6
+
7
+ module Hamlit
8
+ class HamlTempleEngine < Temple::Engine
9
+ define_options(
10
+ attr_wrapper: "'",
11
+ autoclose: %w(area base basefont br col command embed frame
12
+ hr img input isindex keygen link menuitem meta
13
+ param source track wbr),
14
+ encoding: nil,
15
+ escape_attrs: true,
16
+ escape_html: false,
17
+ escape_filter_interpolations: nil,
18
+ filename: '(haml)',
19
+ format: :html5,
20
+ hyphenate_data_attrs: true,
21
+ line: 1,
22
+ mime_type: 'text/html',
23
+ preserve: %w(textarea pre code),
24
+ remove_whitespace: false,
25
+ suppress_eval: false,
26
+ cdata: false,
27
+ parser_class: ::Hamlit::HamlParser,
28
+ compiler_class: ::Hamlit::HamlCompiler,
29
+ trace: false,
30
+ filters: {},
31
+ )
32
+
33
+ use :Parser, -> { options[:parser_class] }
34
+ use :Compiler, -> { options[:compiler_class] }
35
+ use HamlEscapable
36
+ filter :ControlFlow
37
+ filter :MultiFlattener
38
+ filter :StaticMerger
39
+ use HamlGenerator
40
+
41
+ def compile(template)
42
+ initialize_encoding(template, options[:encoding])
43
+ @precompiled = call(template)
44
+ end
45
+
46
+ # The source code that is evaluated to produce the Haml document.
47
+ #
48
+ # This is automatically converted to the correct encoding
49
+ # (see {file:REFERENCE.md#encodings the `:encoding` option}).
50
+ #
51
+ # @return [String]
52
+ def precompiled
53
+ encoding = Encoding.find(@encoding || '')
54
+ return @precompiled.dup.force_encoding(encoding) if encoding == Encoding::ASCII_8BIT
55
+ return @precompiled.encode(encoding)
56
+ end
57
+
58
+ def precompiled_with_return_value
59
+ "#{precompiled};#{precompiled_method_return_value}".dup
60
+ end
61
+
62
+ # The source code that is evaluated to produce the Haml document.
63
+ #
64
+ # This is automatically converted to the correct encoding
65
+ # (see {file:REFERENCE.md#encodings the `:encoding` option}).
66
+ #
67
+ # @return [String]
68
+ def precompiled_with_ambles(local_names, after_preamble: '')
69
+ preamble = <<END.tr("\n", ';')
70
+ begin
71
+ extend Hamlit::HamlHelpers
72
+ _hamlout = @haml_buffer = Hamlit::HamlBuffer.new(haml_buffer, #{HamlOptions.new(options).for_buffer.inspect})
73
+ _erbout = _hamlout.buffer
74
+ #{after_preamble}
75
+ END
76
+ postamble = <<END.tr("\n", ';')
77
+ #{precompiled_method_return_value}
78
+ ensure
79
+ @haml_buffer = @haml_buffer.upper if @haml_buffer
80
+ end
81
+ END
82
+ "#{preamble}#{locals_code(local_names)}#{precompiled}#{postamble}".dup
83
+ end
84
+
85
+ private
86
+
87
+ def initialize_encoding(template, given_value)
88
+ if given_value
89
+ @encoding = given_value
90
+ else
91
+ @encoding = Encoding.default_internal || template.encoding
92
+ end
93
+ end
94
+
95
+ # Returns the string used as the return value of the precompiled method.
96
+ # This method exists so it can be monkeypatched to return modified values.
97
+ def precompiled_method_return_value
98
+ "_erbout"
99
+ end
100
+
101
+ def locals_code(names)
102
+ names = names.keys if Hash === names
103
+
104
+ names.map do |name|
105
+ # Can't use || because someone might explicitly pass in false with a symbol
106
+ sym_local = "_haml_locals[#{inspect_obj(name.to_sym)}]"
107
+ str_local = "_haml_locals[#{inspect_obj(name.to_s)}]"
108
+ "#{name} = #{sym_local}.nil? ? #{str_local} : #{sym_local};"
109
+ end.join
110
+ end
111
+
112
+ def inspect_obj(obj)
113
+ case obj
114
+ when String
115
+ %Q!"#{obj.gsub(/[\x00-\x7F]+/) {|s| s.inspect[1...-1]}}"!
116
+ when Symbol
117
+ ":#{inspect_obj(obj.to_s)}"
118
+ else
119
+ obj.inspect
120
+ end
121
+ end
122
+ end
123
+ end
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  begin
4
4
  require 'erubis/tiny'
@@ -126,7 +126,7 @@ MSG
126
126
  def inspect_obj(obj)
127
127
  case obj
128
128
  when String
129
- %Q!"#{obj.gsub(/[\x00-\x7F]+/) {|s| s.inspect[1...-1]}}"!
129
+ %Q!"#{obj.gsub(/[\x00-\x7F]+/) {|s| s.dump[1...-1]}}"!
130
130
  when Symbol
131
131
  ":#{inspect_obj(obj.to_s)}"
132
132
  else
@@ -166,7 +166,7 @@ MSG
166
166
  # and the rest of the string.
167
167
  # `["Foo (Bar (Baz bang) bop)", " (Bang (bop bip))"]` in the example above.
168
168
  def balance(scanner, start, finish, count = 0)
169
- str = ''
169
+ str = ''.dup
170
170
  scanner = StringScanner.new(scanner) unless scanner.is_a? StringScanner
171
171
  regexp = Regexp.new("(.*?)[\\#{start.chr}\\#{finish.chr}]", Regexp::MULTILINE)
172
172
  while scanner.scan(regexp)
@@ -198,12 +198,9 @@ MSG
198
198
  /#[\{$@]/ === str
199
199
  end
200
200
 
201
- # Original Haml::Util.unescape_interpolation
202
- # ex) slow_unescape_interpolation('foo#{bar}baz"', escape_html: true)
203
- # #=> "\"foo\#{::Hamlit::HamlHelpers.html_escape((bar))}baz\\\"\""
204
- def slow_unescape_interpolation(str, escape_html = nil)
205
- res = ''
206
- rest = ::Hamlit::HamlUtil.handle_interpolation str.dump do |scan|
201
+ def unescape_interpolation(str, escape_html = nil)
202
+ res = ''.dup
203
+ rest = Hamlit::HamlUtil.handle_interpolation str.dump do |scan|
207
204
  escapes = (scan[2].size - 1) / 2
208
205
  char = scan[3] # '{', '@' or '$'
209
206
  res << scan.matched[0...-3 - escapes]
@@ -215,36 +212,9 @@ MSG
215
212
  else
216
213
  scan.scan(/\w+/)
217
214
  end
218
- content = eval('"' + interpolated + '"')
219
- content.prepend(char) if char == '@' || char == '$'
220
- content = "::Hamlit::HamlHelpers.html_escape((#{content}))" if escape_html
221
-
222
- res << "\#{#{content}}"
223
- end
224
- end
225
- res + rest
226
- end
227
-
228
- # Customized Haml::Util.unescape_interpolation to handle escape by Hamlit.
229
- # It wraps double quotes to given `str` with escaping `"`.
230
- #
231
- # ex) unescape_interpolation('foo#{bar}baz"') #=> "\"foo\#{bar}baz\\\"\""
232
- def unescape_interpolation(str)
233
- res = ''
234
- rest = ::Hamlit::HamlUtil.handle_interpolation str.dump do |scan|
235
- escapes = (scan[2].size - 1) / 2
236
- char = scan[3] # '{', '@' or '$'
237
- res << scan.matched[0...-3 - escapes]
238
- if escapes % 2 == 1
239
- res << "\##{char}"
240
- else
241
- interpolated = if char == '{'
242
- balance(scan, ?{, ?}, 1)[0][0...-1]
243
- else
244
- scan.scan(/\w+/)
245
- end
246
- content = eval('"' + interpolated + '"')
247
- content.prepend(char) if char == '@' || char == '$'
215
+ content = eval("\"#{interpolated}\"")
216
+ content = "#{char}#{content}" if char == '@' || char == '$'
217
+ content = "Hamlit::HamlHelpers.html_escape((#{content}))" if escape_html
248
218
 
249
219
  res << "\#{#{content}}"
250
220
  end
@@ -264,7 +234,7 @@ MSG
264
234
  scanner = StringScanner.new(str.dup.force_encoding(Encoding::ASCII_8BIT))
265
235
  bom = scanner.scan(/\xEF\xBB\xBF/n)
266
236
  return bom unless scanner.scan(/-\s*#\s*/n)
267
- if coding = try_parse_haml_emacs_magic_comment(scanner)
237
+ if (coding = try_parse_haml_emacs_magic_comment(scanner))
268
238
  return bom, coding
269
239
  end
270
240
 
@@ -44,7 +44,7 @@ module Hamlit
44
44
 
45
45
  # https://github.com/haml/haml/blob/4.0.7/lib/haml/template.rb
46
46
  module HamlHelpers
47
- require 'hamlit/parser/haml_xss_mods'
47
+ require 'hamlit/parser/haml_helpers/xss_mods'
48
48
  include Hamlit::HamlHelpers::XssMods
49
49
  end
50
50
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'ripper'
2
3
  require 'hamlit/ruby_expression'
3
4
 
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+ module Hamlit
3
+ # A module to count lines of expected code. This would be faster than actual code generation
4
+ # and counting newlines in it.
5
+ module TempleLineCounter
6
+ class UnexpectedExpression < StandardError; end
7
+
8
+ def self.count_lines(exp)
9
+ type, *args = exp
10
+ case type
11
+ when :multi
12
+ args.map { |a| count_lines(a) }.reduce(:+) || 0
13
+ when :dynamic, :code
14
+ args.first.count("\n")
15
+ when :static
16
+ 0 # It has not real newline "\n" but escaped "\\n".
17
+ when :case
18
+ arg, *cases = args
19
+ arg.count("\n") + cases.map do |cond, e|
20
+ (cond == :else ? 0 : cond.count("\n")) + count_lines(e)
21
+ end.reduce(:+)
22
+ when :escape
23
+ count_lines(args[1])
24
+ when :newline
25
+ 1
26
+ else
27
+ raise UnexpectedExpression.new("[HAML BUG] Unexpected Temple expression '#{type}' is given!")
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Hamlit
3
- VERSION = '2.11.0'
3
+ VERSION = '2.13.2'
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hamlit
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.11.0
4
+ version: 2.13.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Takashi Kokubun
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-12-13 00:00:00.000000000 Z
11
+ date: 2020-12-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: temple
@@ -156,14 +156,14 @@ dependencies:
156
156
  requirements:
157
157
  - - ">="
158
158
  - !ruby/object:Gem::Version
159
- version: 4.0.0
159
+ version: '4.0'
160
160
  type: :development
161
161
  prerelease: false
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
164
  - - ">="
165
165
  - !ruby/object:Gem::Version
166
- version: 4.0.0
166
+ version: '4.0'
167
167
  - !ruby/object:Gem::Dependency
168
168
  name: rake
169
169
  requirement: !ruby/object:Gem::Requirement
@@ -257,8 +257,8 @@ extensions:
257
257
  - ext/hamlit/extconf.rb
258
258
  extra_rdoc_files: []
259
259
  files:
260
+ - ".github/workflows/test.yml"
260
261
  - ".gitignore"
261
- - ".travis.yml"
262
262
  - CHANGELOG.md
263
263
  - Gemfile
264
264
  - LICENSE.txt
@@ -287,6 +287,8 @@ files:
287
287
  - benchmark/etc/tags_loop.haml
288
288
  - benchmark/ext/build_data.rb
289
289
  - benchmark/ext/build_id.rb
290
+ - benchmark/graph/graph.key
291
+ - benchmark/graph/graph.png
290
292
  - benchmark/id_attribute.haml
291
293
  - benchmark/plain.haml
292
294
  - benchmark/script.haml
@@ -303,6 +305,7 @@ files:
303
305
  - bin/setup
304
306
  - bin/stackprof
305
307
  - bin/test
308
+ - bin/update-haml
306
309
  - exe/hamlit
307
310
  - ext/hamlit/extconf.rb
308
311
  - ext/hamlit/hamlit.c
@@ -348,22 +351,25 @@ files:
348
351
  - lib/hamlit/identity.rb
349
352
  - lib/hamlit/object_ref.rb
350
353
  - lib/hamlit/parser.rb
351
- - lib/hamlit/parser/MIT-LICENSE
352
- - lib/hamlit/parser/README.md
354
+ - lib/hamlit/parser/haml_attribute_builder.rb
353
355
  - lib/hamlit/parser/haml_buffer.rb
354
356
  - lib/hamlit/parser/haml_compiler.rb
355
357
  - lib/hamlit/parser/haml_error.rb
358
+ - lib/hamlit/parser/haml_escapable.rb
359
+ - lib/hamlit/parser/haml_generator.rb
356
360
  - lib/hamlit/parser/haml_helpers.rb
361
+ - lib/hamlit/parser/haml_helpers/xss_mods.rb
357
362
  - lib/hamlit/parser/haml_options.rb
358
363
  - lib/hamlit/parser/haml_parser.rb
364
+ - lib/hamlit/parser/haml_temple_engine.rb
359
365
  - lib/hamlit/parser/haml_util.rb
360
- - lib/hamlit/parser/haml_xss_mods.rb
361
366
  - lib/hamlit/rails_helpers.rb
362
367
  - lib/hamlit/rails_template.rb
363
368
  - lib/hamlit/railtie.rb
364
369
  - lib/hamlit/ruby_expression.rb
365
370
  - lib/hamlit/string_splitter.rb
366
371
  - lib/hamlit/template.rb
372
+ - lib/hamlit/temple_line_counter.rb
367
373
  - lib/hamlit/utils.rb
368
374
  - lib/hamlit/version.rb
369
375
  homepage: https://github.com/k0kubun/hamlit
@@ -385,7 +391,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
385
391
  - !ruby/object:Gem::Version
386
392
  version: '0'
387
393
  requirements: []
388
- rubygems_version: 3.0.3
394
+ rubygems_version: 3.1.4
389
395
  signing_key:
390
396
  specification_version: 4
391
397
  summary: High Performance Haml Implementation
@@ -1,47 +0,0 @@
1
- language: ruby
2
- cache: bundler
3
- branches:
4
- only:
5
- - master
6
- script:
7
- - "RUBYOPT='-w' bundle exec rake $TASK"
8
- matrix:
9
- include:
10
- - rvm: 2.3.8
11
- env: TASK=test
12
- - rvm: 2.4.5
13
- env: TASK=test
14
- - rvm: 2.5.3
15
- env: TASK=test
16
- - rvm: 2.6.0
17
- env: TASK=test
18
- - rvm: ruby-head
19
- env: TASK=test
20
- - rvm: jruby-9.2.8.0
21
- env: TASK=test
22
- - rvm: truffleruby
23
- env: TASK=test
24
- - rvm: 2.6.0
25
- env: TASK=bench TEMPLATE=benchmark/boolean_attribute.haml,benchmark/class_attribute.haml,benchmark/id_attribute.haml,benchmark/data_attribute.haml,benchmark/common_attribute.haml
26
- - rvm: 2.6.0
27
- env: TASK=bench TEMPLATE=benchmark/dynamic_attributes/boolean_attribute.haml,benchmark/dynamic_attributes/class_attribute.haml,benchmark/dynamic_attributes/id_attribute.haml,benchmark/dynamic_attributes/data_attribute.haml,benchmark/dynamic_attributes/common_attribute.haml
28
- - rvm: 2.6.0
29
- env: TASK=bench SLIM_BENCH=1
30
- - rvm: 2.6.0
31
- env: TASK=bench TEMPLATE=benchmark/etc/attribute_builder.haml
32
- - rvm: 2.6.0
33
- env: TASK=bench TEMPLATE=benchmark/etc/static_analyzer.haml
34
- - rvm: 2.6.0
35
- env: TASK=bench TEMPLATE=benchmark/etc/string_interpolation.haml
36
- - rvm: 2.6.0
37
- env: TASK=bench TEMPLATE=test/haml/templates/standard.haml COMPILE=1
38
- allow_failures:
39
- - rvm: ruby-head
40
- env: TASK=test
41
- - env: TASK=bench TEMPLATE=benchmark/boolean_attribute.haml,benchmark/class_attribute.haml,benchmark/id_attribute.haml,benchmark/data_attribute.haml,benchmark/common_attribute.haml
42
- - env: TASK=bench TEMPLATE=benchmark/dynamic_attributes/boolean_attribute.haml,benchmark/dynamic_attributes/class_attribute.haml,benchmark/dynamic_attributes/id_attribute.haml,benchmark/dynamic_attributes/data_attribute.haml,benchmark/dynamic_attributes/common_attribute.haml
43
- - env: TASK=bench SLIM_BENCH=1
44
- - env: TASK=bench TEMPLATE=benchmark/etc/attribute_builder.haml
45
- - env: TASK=bench TEMPLATE=benchmark/etc/static_analyzer.haml
46
- - env: TASK=bench TEMPLATE=benchmark/etc/string_interpolation.haml
47
- - env: TASK=bench TEMPLATE=test/haml/templates/standard.haml COMPILE=1
@@ -1,20 +0,0 @@
1
- Copyright (c) 2006-2009 Hampton Catlin and Natalie Weizenbaum
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,30 +0,0 @@
1
- # lib/hamlit/parser/haml\_\*.rb
2
-
3
- Hamlit::HamlFoo is originally Haml::Foo in haml gem.
4
-
5
- This directory is NOT intended to be updated other than following Haml's changes.
6
-
7
- ## License
8
-
9
- lib/hamlit/parser/haml\_\*.rb is:
10
-
11
- Copyright (c) 2006-2009 Hampton Catlin and Natalie Weizenbaum
12
-
13
- Permission is hereby granted, free of charge, to any person obtaining
14
- a copy of this software and associated documentation files (the
15
- "Software"), to deal in the Software without restriction, including
16
- without limitation the rights to use, copy, modify, merge, publish,
17
- distribute, sublicense, and/or sell copies of the Software, and to
18
- permit persons to whom the Software is furnished to do so, subject to
19
- the following conditions:
20
-
21
- The above copyright notice and this permission notice shall be
22
- included in all copies or substantial portions of the Software.
23
-
24
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.