hamlit 2.9.4 → 2.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ff5c08623e133d33678ed09abfa8aeb752ff6fe48a203d6d22000430335e0ced
4
- data.tar.gz: caa9eb9872690fc5ae45432c5c8487be7fafe51f2e65f484e6f9602f5afdf4d2
3
+ metadata.gz: 315b433bd4a2af17f13b1a8ff54787c65b25beabcbdb1274dd86b29248e75f60
4
+ data.tar.gz: cd02934b413dd1cf6891f35f5cb1ee8731d68e0f82eb300bf92679b7574ec598
5
5
  SHA512:
6
- metadata.gz: 0d1241f1a8d1fea6d4528649047d5830197b84e3c2bc01c17f8dd07d59f9cc02023b9c28140817f8aeee92ea26bd67ca3bbf864fa3ffeaff83f271d365b87a23
7
- data.tar.gz: 97fcaa8d8b03f6fc84c27927c9a1b73f871211b3d109b32258786a897d54ccb5f3b68c2e42c7e2175dda04073f1dc2aaecb3d3479df34806a5119b035b773968
6
+ metadata.gz: 128daeb6d3f1d34fd33718b90b20b75117cda4147e8783d039b2daf0e019d836ac580d78fd3e01561f53f4348e442d3a04169761048cc2105ef1e3cae5c5c131
7
+ data.tar.gz: 0c11bc8dce803aa8d2adfdc78c7b91274678371adb7d30a8a36d997b60ada32320349712cd39c1feec7d965f5e1bbf6b6ab878a3769d4e20ee245afd1772bf79
data/.gitignore CHANGED
@@ -11,6 +11,7 @@
11
11
  .ruby-version
12
12
  *.bundle
13
13
  *.so
14
+ *.su
14
15
  *.o
15
16
  *.a
16
17
  *.swp
@@ -9,11 +9,13 @@ matrix:
9
9
  include:
10
10
  - rvm: 2.3.8
11
11
  env: TASK=test
12
- - rvm: 2.4.5
12
+ - rvm: 2.4.9
13
13
  env: TASK=test
14
- - rvm: 2.5.3
14
+ - rvm: 2.5.7
15
15
  env: TASK=test
16
- - rvm: 2.6.0
16
+ - rvm: 2.6.5
17
+ env: TASK=test
18
+ - rvm: 2.7.0
17
19
  env: TASK=test
18
20
  - rvm: ruby-head
19
21
  env: TASK=test
@@ -21,19 +23,19 @@ matrix:
21
23
  env: TASK=test
22
24
  - rvm: truffleruby
23
25
  env: TASK=test
24
- - rvm: 2.6.0
26
+ - rvm: 2.7.0
25
27
  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
28
+ - rvm: 2.7.0
27
29
  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
30
+ - rvm: 2.7.0
29
31
  env: TASK=bench SLIM_BENCH=1
30
- - rvm: 2.6.0
32
+ - rvm: 2.7.0
31
33
  env: TASK=bench TEMPLATE=benchmark/etc/attribute_builder.haml
32
- - rvm: 2.6.0
34
+ - rvm: 2.7.0
33
35
  env: TASK=bench TEMPLATE=benchmark/etc/static_analyzer.haml
34
- - rvm: 2.6.0
36
+ - rvm: 2.7.0
35
37
  env: TASK=bench TEMPLATE=benchmark/etc/string_interpolation.haml
36
- - rvm: 2.6.0
38
+ - rvm: 2.7.0
37
39
  env: TASK=bench TEMPLATE=test/haml/templates/standard.haml COMPILE=1
38
40
  allow_failures:
39
41
  - rvm: ruby-head
@@ -4,6 +4,43 @@ All notable changes to this project will be documented in this file. This
4
4
  project adheres to [Semantic Versioning](http://semver.org/). This change log is based upon
5
5
  [keep-a-changelog](https://github.com/olivierlacan/keep-a-changelog).
6
6
 
7
+ ## [2.11.1](https://github.com/k0kubun/hamlit/compare/v2.11.0...v2.11.1) - 2020-08-25
8
+
9
+ ### Fixed
10
+
11
+ - Fix a line number on an error after filters like preserve, plain, and ruby.
12
+ *Thanks to @rgisiger*
13
+
14
+ ## [2.11.0](https://github.com/k0kubun/hamlit/compare/v2.10.1...v2.11.0) - 2019-12-12
15
+
16
+ ### Added
17
+
18
+ - Support Haml's _revealed_ conditional comment feature on `/![if !IE]` [#153](https://github.com/k0kubun/hamlit/issues/153).
19
+ *Thanks to @esb*
20
+
21
+ ## [2.10.1](https://github.com/k0kubun/hamlit/compare/v2.10.0...v2.10.1) - 2019-11-28
22
+
23
+ ### Added
24
+
25
+ - Register `Hamlit::Template` to Tilt as :hamlit as well, in addition to :haml
26
+
27
+ ## [2.10.0](https://github.com/k0kubun/hamlit/compare/v2.9.5...v2.10.0) - 2019-09-15
28
+
29
+ ### Added
30
+
31
+ - Optimize template rendering by string interpolation [#146](https://github.com/k0kubun/hamlit/issues/146)
32
+ - Exploiting pre-allocation of string interpolation introduced in Ruby 2.5 [ruby/ruby#1626](https://github.com/ruby/ruby/pull/1626)
33
+
34
+ ### Changed
35
+
36
+ - Require temple.gem >= 0.8.2
37
+
38
+ ## [2.9.5](https://github.com/k0kubun/hamlit/compare/v2.9.4...v2.9.5) - 2019-09-08
39
+
40
+ ### Added
41
+
42
+ - Supported `:plain` filter in truffleruby
43
+
7
44
  ## [2.9.4](https://github.com/k0kubun/hamlit/compare/v2.9.3...v2.9.4) - 2019-09-08
8
45
 
9
46
  ### Added
data/Gemfile CHANGED
@@ -14,17 +14,15 @@ end
14
14
 
15
15
  gem 'benchmark-ips', '2.3.0'
16
16
  gem 'maxitest'
17
+ gem 'pry'
17
18
 
18
19
  if /java/ === RUBY_PLATFORM # JRuby
19
20
  gem 'pandoc-ruby'
20
21
  else
21
- gem 'pry-byebug'
22
22
  gem 'redcarpet'
23
23
 
24
24
  if RUBY_PLATFORM !~ /mswin|mingw/ && RUBY_ENGINE != 'truffleruby'
25
- if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7.0') # Travis cannot compile ruby.h with C++
26
- gem 'faml'
27
- end
25
+ gem 'faml'
28
26
  gem 'stackprof'
29
27
  end
30
28
  end
@@ -57,6 +57,7 @@ for full features in original implementation.
57
57
  - [x] :plain
58
58
  - [x] :preserve
59
59
  - [x] :ruby
60
+ - `haml_io` API is not supported. Use [hamlit-haml\_io.gem](https://github.com/hamlit/hamlit-haml_io) if you need.
60
61
  - [x] :sass
61
62
  - [x] :scss
62
63
  - [ ] :textile
@@ -121,10 +122,10 @@ and merging multiple ids results in concatenation by "\_".
121
122
  %div{ id: false }
122
123
 
123
124
  # Output
124
- <div id='foo_bar'></span>
125
- <div id='foo_bar'></span>
126
- <div id='foo_bar'></span>
127
- <div id=''></span>
125
+ <div id='foo_bar'></div>
126
+ <div id='foo_bar'></div>
127
+ <div id='foo_bar'></div>
128
+ <div id=''></div>
128
129
  ```
129
130
 
130
131
  ### class attribute
@@ -224,6 +225,14 @@ Hamlit::RailsTemplate.set_options attr_quote: '"'
224
225
  set :haml, { attr_quote: '"' }
225
226
  ```
226
227
 
228
+ ## Ruby module
229
+
230
+ `Hamlit::Template` is a module registered to `Tilt`. You can use it like:
231
+
232
+ ```rb
233
+ Hamlit::Template.new { "%strong Yay for HAML!" }.render
234
+ ```
235
+
227
236
  ## Creating a custom filter
228
237
 
229
238
  Currently it doesn't have filter registering interface compatible with Haml.
@@ -0,0 +1,25 @@
1
+ # Original: https://github.com/amatsuda/string_template/blob/master/benchmark.rb
2
+ require 'benchmark_driver'
3
+
4
+ Benchmark.driver(repeat_count: 8) do |x|
5
+ x.prelude %{
6
+ require 'rails'
7
+ require 'action_view'
8
+ require 'string_template'
9
+ StringTemplate::Railtie.run_initializers
10
+ require 'hamlit'
11
+ Hamlit::Railtie.run_initializers
12
+ Hamlit::RailsTemplate.set_options(escape_html: false, generator: Temple::Generators::ArrayBuffer)
13
+ require 'action_view/base'
14
+
15
+ (view = Class.new(ActionView::Base).new(ActionView::LookupContext.new(''))).instance_variable_set(:@world, 'world!')
16
+
17
+ # compile template
18
+ hello = 'benchmark/dynamic_merger/hello'
19
+ view.render(template: hello, handlers: 'string')
20
+ view.render(template: hello, handlers: 'haml')
21
+ }
22
+ x.report 'string', %{ view.render(template: hello, handlers: 'string') }
23
+ x.report 'hamlit', %{ view.render(template: hello, handlers: 'haml') }
24
+ x.loop_count 100_000
25
+ end
@@ -0,0 +1,50 @@
1
+ hello, #{ @world }
2
+ hello, #{ @world }
3
+ hello, #{ @world }
4
+ hello, #{ @world }
5
+ hello, #{ @world }
6
+ hello, #{ @world }
7
+ hello, #{ @world }
8
+ hello, #{ @world }
9
+ hello, #{ @world }
10
+ hello, #{ @world }
11
+ hello, #{ @world }
12
+ hello, #{ @world }
13
+ hello, #{ @world }
14
+ hello, #{ @world }
15
+ hello, #{ @world }
16
+ hello, #{ @world }
17
+ hello, #{ @world }
18
+ hello, #{ @world }
19
+ hello, #{ @world }
20
+ hello, #{ @world }
21
+ hello, #{ @world }
22
+ hello, #{ @world }
23
+ hello, #{ @world }
24
+ hello, #{ @world }
25
+ hello, #{ @world }
26
+ hello, #{ @world }
27
+ hello, #{ @world }
28
+ hello, #{ @world }
29
+ hello, #{ @world }
30
+ hello, #{ @world }
31
+ hello, #{ @world }
32
+ hello, #{ @world }
33
+ hello, #{ @world }
34
+ hello, #{ @world }
35
+ hello, #{ @world }
36
+ hello, #{ @world }
37
+ hello, #{ @world }
38
+ hello, #{ @world }
39
+ hello, #{ @world }
40
+ hello, #{ @world }
41
+ hello, #{ @world }
42
+ hello, #{ @world }
43
+ hello, #{ @world }
44
+ hello, #{ @world }
45
+ hello, #{ @world }
46
+ hello, #{ @world }
47
+ hello, #{ @world }
48
+ hello, #{ @world }
49
+ hello, #{ @world }
50
+ hello, #{ @world }
@@ -0,0 +1,50 @@
1
+ hello, #{ @world }
2
+ hello, #{ @world }
3
+ hello, #{ @world }
4
+ hello, #{ @world }
5
+ hello, #{ @world }
6
+ hello, #{ @world }
7
+ hello, #{ @world }
8
+ hello, #{ @world }
9
+ hello, #{ @world }
10
+ hello, #{ @world }
11
+ hello, #{ @world }
12
+ hello, #{ @world }
13
+ hello, #{ @world }
14
+ hello, #{ @world }
15
+ hello, #{ @world }
16
+ hello, #{ @world }
17
+ hello, #{ @world }
18
+ hello, #{ @world }
19
+ hello, #{ @world }
20
+ hello, #{ @world }
21
+ hello, #{ @world }
22
+ hello, #{ @world }
23
+ hello, #{ @world }
24
+ hello, #{ @world }
25
+ hello, #{ @world }
26
+ hello, #{ @world }
27
+ hello, #{ @world }
28
+ hello, #{ @world }
29
+ hello, #{ @world }
30
+ hello, #{ @world }
31
+ hello, #{ @world }
32
+ hello, #{ @world }
33
+ hello, #{ @world }
34
+ hello, #{ @world }
35
+ hello, #{ @world }
36
+ hello, #{ @world }
37
+ hello, #{ @world }
38
+ hello, #{ @world }
39
+ hello, #{ @world }
40
+ hello, #{ @world }
41
+ hello, #{ @world }
42
+ hello, #{ @world }
43
+ hello, #{ @world }
44
+ hello, #{ @world }
45
+ hello, #{ @world }
46
+ hello, #{ @world }
47
+ hello, #{ @world }
48
+ hello, #{ @world }
49
+ hello, #{ @world }
50
+ hello, #{ @world }
data/bin/bench CHANGED
@@ -25,7 +25,7 @@ class Bench < Thor
25
25
  haml = File.read(file)
26
26
 
27
27
  Benchmark.ips do |x|
28
- x.report("haml v#{Haml::VERSION}") { Haml::Engine.new(haml, escape_html: true, escape_attrs: true, ugly: true).precompiled }
28
+ x.report("haml v#{Haml::VERSION}") { Haml::Engine.new(haml, escape_html: true, escape_attrs: true).precompiled }
29
29
  x.report("faml v#{Faml::VERSION}") { Faml::Engine.new.call(haml) }
30
30
  x.report("hamlit v#{Hamlit::VERSION}") { Hamlit::Engine.new.call(haml) }
31
31
  x.compare!
@@ -43,7 +43,7 @@ class Bench < Thor
43
43
  object.instance_eval(File.read(ruby_file))
44
44
  end
45
45
 
46
- Haml::Engine.new(haml, escape_html: true, escape_attrs: true, ugly: true).def_method(object, :haml)
46
+ Haml::Engine.new(haml, escape_html: true, escape_attrs: true).def_method(object, :haml)
47
47
  object.instance_eval "def faml; #{Faml::Engine.new.call(haml)}; end"
48
48
  object.instance_eval "def hamlit; #{Hamlit::Engine.new.call(haml)}; end"
49
49
 
@@ -59,7 +59,7 @@ class Bench < Thor
59
59
  def code(file)
60
60
  haml = File.read(file)
61
61
  puts "#{?= * 49}\n Haml Source: #{file}\n#{?= * 49}"
62
- puts Haml::Engine.new(haml, escape_html: true, escape_attrs: true, ugly: true).precompiled
62
+ puts Haml::Engine.new(haml, escape_html: true, escape_attrs: true).precompiled
63
63
  puts "\n#{?= * 49}\n Faml Source: #{file}\n#{?= * 49}"
64
64
  puts Faml::Engine.new.call(haml)
65
65
  puts "\n#{?= * 49}\n Hamlit Source: #{file}\n#{?= * 49}"
@@ -26,10 +26,11 @@ Gem::Specification.new do |spec|
26
26
  spec.required_ruby_version = '>= 2.1.0'
27
27
  end
28
28
 
29
- spec.add_dependency 'temple', '>= 0.8.0'
29
+ spec.add_dependency 'temple', '>= 0.8.2'
30
30
  spec.add_dependency 'thor'
31
31
  spec.add_dependency 'tilt'
32
32
 
33
+ spec.add_development_dependency 'benchmark_driver'
33
34
  spec.add_development_dependency 'bundler'
34
35
  spec.add_development_dependency 'coffee-script'
35
36
  spec.add_development_dependency 'erubi'
@@ -41,5 +42,6 @@ Gem::Specification.new do |spec|
41
42
  spec.add_development_dependency 'rake-compiler'
42
43
  spec.add_development_dependency 'sass'
43
44
  spec.add_development_dependency 'slim'
45
+ spec.add_development_dependency 'string_template'
44
46
  spec.add_development_dependency 'unindent'
45
47
  end
@@ -1,4 +1,6 @@
1
1
  # frozen_string_literal: true
2
+ require 'hamlit/temple_line_counter'
3
+
2
4
  module Hamlit
3
5
  class Compiler
4
6
  class ChildrenCompiler
@@ -14,7 +16,7 @@ module Hamlit
14
16
  node.children.each do |n|
15
17
  rstrip_whitespace!(temple) if nuke_prev_whitespace?(n)
16
18
  insert_newlines!(temple, n)
17
- temple << yield(n)
19
+ temple << moving_lineno(n) { block.call(n) }
18
20
  temple << :whitespace if insert_whitespace?(n)
19
21
  end
20
22
  rstrip_whitespace!(temple) if nuke_inner_whitespace?(node)
@@ -27,19 +29,31 @@ module Hamlit
27
29
  (node.line - @lineno).times do
28
30
  temple << [:newline]
29
31
  end
32
+
30
33
  @lineno = node.line
34
+ end
31
35
 
36
+ def moving_lineno(node, &block)
37
+ # before: As they may have children, we need to increment lineno before compilation.
32
38
  case node.type
33
39
  when :script, :silent_script
34
40
  @lineno += 1
35
- when :filter
36
- @lineno += (node.value[:text] || '').split("\n").size
37
41
  when :tag
38
42
  node.value[:attributes_hashes].each do |attribute_hash|
39
43
  @lineno += attribute_hash.count("\n")
40
44
  end
41
45
  @lineno += 1 if node.children.empty? && node.value[:parse]
42
46
  end
47
+
48
+ temple = block.call # compile
49
+
50
+ # after: filter may not have children, and for some dynamic filters we can't predict the number of lines.
51
+ case node.type
52
+ when :filter
53
+ @lineno += TempleLineCounter.count_lines(temple)
54
+ end
55
+
56
+ temple
43
57
  end
44
58
 
45
59
  def confirm_whitespace(temple)
@@ -25,11 +25,13 @@ module Hamlit
25
25
  condition = $1
26
26
  end
27
27
 
28
- if node.children.empty?
29
- [:html, :condcomment, condition, [:static, " #{node.value[:text]} "]]
30
- else
31
- [:html, :condcomment, condition, yield(node)]
32
- end
28
+ content =
29
+ if node.children.empty?
30
+ [:static, " #{node.value[:text]} "]
31
+ else
32
+ yield(node)
33
+ end
34
+ [:html, :condcomment, condition, content, node.value[:revealed]]
33
35
  end
34
36
  end
35
37
  end
@@ -55,10 +55,6 @@ module Hamlit
55
55
 
56
56
  # We should handle interpolation here to escape only interpolated values.
57
57
  def compile_interpolated_plain(node)
58
- unless Ripper.respond_to?(:lex) # No Ripper.lex in truffleruby
59
- return [:multi, [:escape, node.value[:escape_interpolation], [:dynamic, "%Q[#{node.value[:value]}]"]], [:newline]]
60
- end
61
-
62
58
  temple = [:multi]
63
59
  StringSplitter.compile(node.value[:value]).each do |type, value|
64
60
  case type
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+ module Hamlit
3
+ # Compile [:multi, [:static, 'foo'], [:dynamic, 'bar']] to [:dynamic, '"foo#{bar}"']
4
+ class DynamicMerger < Temple::Filter
5
+ def on_multi(*exps)
6
+ exps = exps.dup
7
+ result = [:multi]
8
+ buffer = []
9
+
10
+ until exps.empty?
11
+ type, arg = exps.first
12
+ if type == :dynamic && arg.count("\n") == 0
13
+ buffer << exps.shift
14
+ elsif type == :static && exps.size > (count = arg.count("\n")) &&
15
+ exps[1, count].all? { |e| e == [:newline] }
16
+ (1 + count).times { buffer << exps.shift }
17
+ elsif type == :newline && exps.size > (count = count_newline(exps)) &&
18
+ exps[count].first == :static && count == exps[count].last.count("\n")
19
+ (count + 1).times { buffer << exps.shift }
20
+ else
21
+ result.concat(merge_dynamic(buffer))
22
+ buffer = []
23
+ result << compile(exps.shift)
24
+ end
25
+ end
26
+ result.concat(merge_dynamic(buffer))
27
+
28
+ result.size == 2 ? result[1] : result
29
+ end
30
+
31
+ private
32
+
33
+ def merge_dynamic(exps)
34
+ # Merge exps only when they have both :static and :dynamic
35
+ unless exps.any? { |type,| type == :static } && exps.any? { |type,| type == :dynamic }
36
+ return exps
37
+ end
38
+
39
+ strlit_body = String.new
40
+ exps.each do |type, arg|
41
+ case type
42
+ when :static
43
+ strlit_body << arg.dump.sub!(/\A"/, '').sub!(/"\z/, '').gsub('\n', "\n")
44
+ when :dynamic
45
+ strlit_body << "\#{#{arg}}"
46
+ when :newline
47
+ # newline is added by `gsub('\n', "\n")`
48
+ else
49
+ raise "unexpected type #{type.inspect} is given to #merge_dynamic"
50
+ end
51
+ end
52
+ [[:dynamic, "%Q\0#{strlit_body}\0"]]
53
+ end
54
+
55
+ def count_newline(exps)
56
+ count = 0
57
+ exps.each do |exp|
58
+ if exp == [:newline]
59
+ count += 1
60
+ else
61
+ return count
62
+ end
63
+ end
64
+ return count
65
+ end
66
+ end
67
+ end
@@ -2,10 +2,10 @@
2
2
  require 'temple'
3
3
  require 'hamlit/parser'
4
4
  require 'hamlit/compiler'
5
+ require 'hamlit/html'
5
6
  require 'hamlit/escapable'
6
7
  require 'hamlit/force_escapable'
7
- require 'hamlit/html'
8
- require 'hamlit/string_splitter'
8
+ require 'hamlit/dynamic_merger'
9
9
 
10
10
  module Hamlit
11
11
  class Engine < Temple::Engine
@@ -25,15 +25,14 @@ module Hamlit
25
25
  use Parser
26
26
  use Compiler
27
27
  use HTML
28
- if Ripper.respond_to?(:lex) # No Ripper.lex in truffleruby
29
- use StringSplitter
30
- filter :StaticAnalyzer
31
- end
28
+ filter :StringSplitter
29
+ filter :StaticAnalyzer
32
30
  use Escapable
33
31
  use ForceEscapable
34
32
  filter :ControlFlow
35
33
  filter :MultiFlattener
36
34
  filter :StaticMerger
35
+ use DynamicMerger
37
36
  use :Generator, -> { options[:generator] }
38
37
  end
39
38
  end
@@ -5,9 +5,6 @@ module Hamlit
5
5
  class Filters
6
6
  class Plain < Base
7
7
  def compile(node)
8
- unless Ripper.respond_to?(:lex)
9
- raise NotImplementedError.new('This platform does not have Ripper.lex required for :plain filter')
10
- end
11
8
  text = node.value[:text]
12
9
  text = text.rstrip unless ::Hamlit::HamlUtil.contains_interpolation?(text) # for compatibility
13
10
  [:multi, *compile_plain(text)]
@@ -10,5 +10,13 @@ module Hamlit
10
10
  end
11
11
  super(opts)
12
12
  end
13
+
14
+ # This dispatcher supports Haml's "revealed" conditional comment.
15
+ def on_html_condcomment(condition, content, revealed = false)
16
+ on_html_comment [:multi,
17
+ [:static, "[#{condition}]>#{'<!-->' if revealed}"],
18
+ content,
19
+ [:static, "#{'<!--' if revealed}<![endif]"]]
20
+ end
13
21
  end
14
22
  end
@@ -2,87 +2,18 @@ require 'ripper'
2
2
  require 'hamlit/ruby_expression'
3
3
 
4
4
  module Hamlit
5
- class StringSplitter < Temple::Filter
6
- class << self
7
- # `code` param must be valid string literal
8
- def compile(code)
9
- [].tap do |exps|
10
- tokens = Ripper.lex(code.strip)
11
- tokens.pop while tokens.last && %i[on_comment on_sp].include?(tokens.last[1])
12
-
13
- if tokens.size < 2
14
- raise Hamlit::InternalError.new("Expected token size >= 2 but got: #{tokens.size}")
15
- end
16
- compile_tokens!(exps, tokens)
17
- end
18
- end
19
-
20
- private
21
-
22
- def strip_quotes!(tokens)
23
- _, type, beg_str = tokens.shift
24
- if type != :on_tstring_beg
25
- raise Hamlit::InternalError.new("Expected :on_tstring_beg but got: #{type}")
26
- end
27
-
28
- _, type, end_str = tokens.pop
29
- if type != :on_tstring_end
30
- raise Hamlit::InternalError.new("Expected :on_tstring_end but got: #{type}")
31
- end
32
-
33
- [beg_str, end_str]
34
- end
35
-
36
- def compile_tokens!(exps, tokens)
37
- beg_str, end_str = strip_quotes!(tokens)
38
-
39
- until tokens.empty?
40
- _, type, str = tokens.shift
41
-
42
- case type
43
- when :on_tstring_content
44
- exps << [:static, eval("#{beg_str}#{str}#{end_str}")]
45
- when :on_embexpr_beg
46
- embedded = shift_balanced_embexpr(tokens)
47
- exps << [:dynamic, embedded] unless embedded.empty?
48
- end
49
- end
50
- end
51
-
52
- def shift_balanced_embexpr(tokens)
53
- String.new.tap do |embedded|
54
- embexpr_open = 1
55
-
56
- until tokens.empty?
57
- _, type, str = tokens.shift
58
- case type
59
- when :on_embexpr_beg
60
- embexpr_open += 1
61
- when :on_embexpr_end
62
- embexpr_open -= 1
63
- break if embexpr_open == 0
64
- end
65
-
66
- embedded << str
67
- end
68
- end
5
+ module StringSplitter
6
+ # `code` param must be valid string literal
7
+ def self.compile(code)
8
+ unless Ripper.respond_to?(:lex) # truffleruby doesn't have Ripper.lex
9
+ return [[:dynamic, code]]
69
10
  end
70
- end
71
-
72
- def on_dynamic(code)
73
- return [:dynamic, code] unless RubyExpression.string_literal?(code)
74
- return [:dynamic, code] if code.include?("\n")
75
11
 
76
- temple = [:multi]
77
- StringSplitter.compile(code).each do |type, content|
78
- case type
79
- when :static
80
- temple << [:static, content]
81
- when :dynamic
82
- temple << on_dynamic(content)
83
- end
12
+ begin
13
+ Temple::Filters::StringSplitter.compile(code)
14
+ rescue Temple::FilterError => e
15
+ raise Hamlit::InternalError.new(e.message)
84
16
  end
85
- temple
86
17
  end
87
18
  end
88
19
  end
@@ -14,7 +14,7 @@ end
14
14
  module Hamlit
15
15
  Template = Temple::Templates::Tilt.create(
16
16
  Hamlit::Engine,
17
- register_as: :haml,
17
+ register_as: [:haml, :hamlit],
18
18
  )
19
19
 
20
20
  module TemplateExtension
@@ -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.9.4'
3
+ VERSION = '2.11.1'
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.9.4
4
+ version: 2.11.1
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-09-08 00:00:00.000000000 Z
11
+ date: 2020-08-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: temple
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 0.8.0
19
+ version: 0.8.2
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 0.8.0
26
+ version: 0.8.2
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: thor
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: benchmark_driver
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: bundler
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -206,6 +220,20 @@ dependencies:
206
220
  - - ">="
207
221
  - !ruby/object:Gem::Version
208
222
  version: '0'
223
+ - !ruby/object:Gem::Dependency
224
+ name: string_template
225
+ requirement: !ruby/object:Gem::Requirement
226
+ requirements:
227
+ - - ">="
228
+ - !ruby/object:Gem::Version
229
+ version: '0'
230
+ type: :development
231
+ prerelease: false
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ requirements:
234
+ - - ">="
235
+ - !ruby/object:Gem::Version
236
+ version: '0'
209
237
  - !ruby/object:Gem::Dependency
210
238
  name: unindent
211
239
  requirement: !ruby/object:Gem::Requirement
@@ -247,6 +275,9 @@ files:
247
275
  - benchmark/dynamic_attributes/data_attribute.haml
248
276
  - benchmark/dynamic_attributes/id_attribute.haml
249
277
  - benchmark/dynamic_boolean_attribute.haml
278
+ - benchmark/dynamic_merger/benchmark.rb
279
+ - benchmark/dynamic_merger/hello.haml
280
+ - benchmark/dynamic_merger/hello.string
250
281
  - benchmark/etc/attribute_builder.haml
251
282
  - benchmark/etc/real_sample.haml
252
283
  - benchmark/etc/real_sample.rb
@@ -290,6 +321,7 @@ files:
290
321
  - lib/hamlit/compiler/script_compiler.rb
291
322
  - lib/hamlit/compiler/silent_script_compiler.rb
292
323
  - lib/hamlit/compiler/tag_compiler.rb
324
+ - lib/hamlit/dynamic_merger.rb
293
325
  - lib/hamlit/engine.rb
294
326
  - lib/hamlit/error.rb
295
327
  - lib/hamlit/escapable.rb
@@ -311,7 +343,6 @@ files:
311
343
  - lib/hamlit/filters/text_base.rb
312
344
  - lib/hamlit/filters/tilt_base.rb
313
345
  - lib/hamlit/force_escapable.rb
314
- - lib/hamlit/hamlit.su
315
346
  - lib/hamlit/helpers.rb
316
347
  - lib/hamlit/html.rb
317
348
  - lib/hamlit/identity.rb
@@ -333,6 +364,7 @@ files:
333
364
  - lib/hamlit/ruby_expression.rb
334
365
  - lib/hamlit/string_splitter.rb
335
366
  - lib/hamlit/template.rb
367
+ - lib/hamlit/temple_line_counter.rb
336
368
  - lib/hamlit/utils.rb
337
369
  - lib/hamlit/version.rb
338
370
  homepage: https://github.com/k0kubun/hamlit
@@ -354,7 +386,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
354
386
  - !ruby/object:Gem::Version
355
387
  version: '0'
356
388
  requirements: []
357
- rubygems_version: 3.0.3
389
+ rubygems_version: 3.1.2
358
390
  signing_key:
359
391
  specification_version: 4
360
392
  summary: High Performance Haml Implementation
Binary file