temple 0.7.7 → 0.8.0

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
  SHA1:
3
- metadata.gz: 70234f9ea5cb84da4b1a8cdcfc8f63056d8af5ce
4
- data.tar.gz: 4b76d19c5643183eb268c83dffc968f777c8d97a
3
+ metadata.gz: 524637aaba62c678fcfe02760bb49ec94a2073c3
4
+ data.tar.gz: a342126edf52f3e3578c4cc9f70540aed6b32b84
5
5
  SHA512:
6
- metadata.gz: 9c7ec6543f4fc8d3d95fc5046a606135605886b5e0ab67deb50e311ae50b5ff7b3030971173ca42d1ca8b67a45c33427b2b2cbaaac0b071f02d17dfcae0ef274
7
- data.tar.gz: a8fb82e723319e0b4f1b11cd33c7b155f1cebda73345bf418b22626bd23b566b85904e45474535c8406fdd9693c6e1a7d75547b9c9d323d8b298cb9bffa86c50
6
+ metadata.gz: 1bbc62f26373b9fb48c57cad57672ef3c379af1b991ba2538f3d7b699f6f0c22b19199520849869463349af07b810946a52029c345e7ec532aa81fb8b893d1e8
7
+ data.tar.gz: 98da558eb0435b349b4c5ee44c407c92c07ee7eba8d08619d8a5158e447c423e16693707a052077ac4822aea810b1784f7fa0cc446fcf2648267b17dced0f421
@@ -1,13 +1,17 @@
1
1
  language: ruby
2
+ dist: trusty
3
+
4
+ cache: bundler
2
5
 
3
6
  rvm:
4
7
  - 1.9.3
5
8
  - 2.0.0
6
- - 2.1.0
7
- - 2.3.0
9
+ - 2.1.10
10
+ - 2.2.6
11
+ - 2.3.3
8
12
  - ruby-head
9
13
  - jruby-19mode
10
- - rbx-2
14
+ - rbx-3
11
15
 
12
16
  sudo: false
13
17
 
@@ -18,3 +22,9 @@ env:
18
22
  matrix:
19
23
  allow_failures:
20
24
  - rvm: ruby-head
25
+ - rvm: rbx-3
26
+ exclude:
27
+ - rvm: jruby-19mode
28
+ env: ESCAPE_UTILS=1
29
+ - rvm: rbx-3
30
+ env: ESCAPE_UTILS=1
data/CHANGES CHANGED
@@ -1,6 +1,15 @@
1
+ 0.8.0
2
+
3
+ * Add Temple::StaticAnalyzer to analyze Ruby expressions
4
+ * Support newlines in Temple::Filters::StaticAnalyzer
5
+
6
+ 0.7.8
7
+
8
+ * Fix an warning in StaticAnalyzer
9
+
1
10
  0.7.7
2
11
 
3
- * Add StaticAnalyzer, StringSplitter
12
+ * Add Temple::Filters::StaticAnalyzer, Temple::Filters::StringSplitter
4
13
  * Freeze string literals
5
14
 
6
15
  0.7.6
@@ -227,6 +227,7 @@ Example:
227
227
  [:html, :tag, 'img', [:html, :attrs, [:html, :attr, 'src', 'image.png']]]
228
228
  [:html, :tag, 'p', [:multi], [:static, 'Content']]
229
229
  generates:
230
+
230
231
  <img src="image.png"/>
231
232
  <p>Content</p>
232
233
 
@@ -13,6 +13,7 @@ module Temple
13
13
  autoload :ImmutableMap, 'temple/map'
14
14
  autoload :MutableMap, 'temple/map'
15
15
  autoload :OptionMap, 'temple/map'
16
+ autoload :StaticAnalyzer, 'temple/static_analyzer'
16
17
 
17
18
  module Mixins
18
19
  autoload :Dispatcher, 'temple/mixins/dispatcher'
@@ -1,85 +1,28 @@
1
- begin
2
- require 'ripper'
3
- rescue LoadError
4
- end
5
-
6
1
  module Temple
7
2
  module Filters
8
3
  # Convert [:dynamic, code] to [:static, text] if code is static Ruby expression.
9
4
  class StaticAnalyzer < Filter
10
- STATIC_TOKENS = [
11
- :on_tstring_beg, :on_tstring_end, :on_tstring_content,
12
- :on_embexpr_beg, :on_embexpr_end,
13
- :on_lbracket, :on_rbracket,
14
- :on_qwords_beg, :on_words_sep, :on_qwords_sep,
15
- :on_lparen, :on_rparen,
16
- :on_lbrace, :on_rbrace, :on_label,
17
- :on_int, :on_float, :on_imaginary,
18
- :on_comma, :on_sp,
19
- ].freeze
20
-
21
- DYNAMIC_TOKENS = [
22
- :on_ident, :on_period,
23
- ].freeze
24
-
25
- STATIC_KEYWORDS = [
26
- 'true', 'false', 'nil',
27
- ].freeze
28
-
29
- STATIC_OPERATORS = [
30
- '=>',
31
- ].freeze
32
-
33
- if defined?(Ripper)
34
- def self.static?(code)
35
- return false if code.nil? || code.strip.empty?
36
- return false if SyntaxChecker.syntax_error?(code)
37
-
38
- Ripper.lex(code).each do |(_, col), token, str|
39
- case token
40
- when *STATIC_TOKENS
41
- # noop
42
- when :on_kw
43
- return false unless STATIC_KEYWORDS.include?(str)
44
- when :on_op
45
- return false unless STATIC_OPERATORS.include?(str)
46
- when *DYNAMIC_TOKENS
47
- return false
48
- else
49
- return false
50
- end
51
- end
52
- true
53
- end
54
-
55
- def on_dynamic(code)
56
- if StaticAnalyzer.static?(code)
57
- [:static, eval(code).to_s]
58
- else
59
- [:dynamic, code]
60
- end
5
+ def call(exp)
6
+ # Optimize only when Ripper is available.
7
+ if ::Temple::StaticAnalyzer.available?
8
+ super
9
+ else
10
+ exp
61
11
  end
12
+ end
62
13
 
63
- class SyntaxChecker < Ripper
64
- class ParseError < StandardError; end
65
-
66
- def self.syntax_error?(code)
67
- self.new(code).parse
68
- false
69
- rescue ParseError
70
- true
71
- end
72
-
73
- private
14
+ def on_dynamic(code)
15
+ if ::Temple::StaticAnalyzer.static?(code)
16
+ exp = [:static, eval(code).to_s]
74
17
 
75
- def on_parse_error(*)
76
- raise ParseError
18
+ newlines = code.count("\n")
19
+ if newlines == 0
20
+ exp
21
+ else
22
+ [:multi, exp, *newlines.times.map { [:newline] }]
77
23
  end
78
- end
79
- else
80
- # Do nothing if ripper is unavailable
81
- def call(ast)
82
- ast
24
+ else
25
+ [:dynamic, code]
83
26
  end
84
27
  end
85
28
  end
@@ -16,7 +16,7 @@ module Temple
16
16
  tokens.pop while tokens.last && [:on_comment, :on_sp].include?(tokens.last[1])
17
17
 
18
18
  if tokens.size < 2
19
- raise "Expected token size >= 2 but got: #{tokens.size}"
19
+ raise(FilterError, "Expected token size >= 2 but got: #{tokens.size}")
20
20
  end
21
21
  compile_tokens!(exps, tokens)
22
22
  end
@@ -27,12 +27,12 @@ module Temple
27
27
  def strip_quotes!(tokens)
28
28
  _, type, beg_str = tokens.shift
29
29
  if type != :on_tstring_beg
30
- raise "Expected :on_tstring_beg but got: #{type}"
30
+ raise(FilterError, "Expected :on_tstring_beg but got: #{type}")
31
31
  end
32
32
 
33
33
  _, type, end_str = tokens.pop
34
34
  if type != :on_tstring_end
35
- raise "Expected :on_tstring_end but got: #{type}"
35
+ raise(FilterError, "Expected :on_tstring_end but got: #{type}")
36
36
  end
37
37
 
38
38
  [beg_str, end_str]
@@ -0,0 +1,77 @@
1
+ begin
2
+ require 'ripper'
3
+ rescue LoadError
4
+ end
5
+
6
+ module Temple
7
+ module StaticAnalyzer
8
+ STATIC_TOKENS = [
9
+ :on_tstring_beg, :on_tstring_end, :on_tstring_content,
10
+ :on_embexpr_beg, :on_embexpr_end,
11
+ :on_lbracket, :on_rbracket,
12
+ :on_qwords_beg, :on_words_sep, :on_qwords_sep,
13
+ :on_lparen, :on_rparen,
14
+ :on_lbrace, :on_rbrace, :on_label,
15
+ :on_int, :on_float, :on_imaginary,
16
+ :on_comma, :on_sp, :on_ignored_nl,
17
+ ].freeze
18
+
19
+ DYNAMIC_TOKENS = [
20
+ :on_ident, :on_period,
21
+ ].freeze
22
+
23
+ STATIC_KEYWORDS = [
24
+ 'true', 'false', 'nil',
25
+ ].freeze
26
+
27
+ STATIC_OPERATORS = [
28
+ '=>',
29
+ ].freeze
30
+
31
+ class << self
32
+ def available?
33
+ defined?(Ripper)
34
+ end
35
+
36
+ def static?(code)
37
+ return false if code.nil? || code.strip.empty?
38
+ return false if syntax_error?(code)
39
+
40
+ Ripper.lex(code).each do |_, token, str|
41
+ case token
42
+ when *STATIC_TOKENS
43
+ # noop
44
+ when :on_kw
45
+ return false unless STATIC_KEYWORDS.include?(str)
46
+ when :on_op
47
+ return false unless STATIC_OPERATORS.include?(str)
48
+ when *DYNAMIC_TOKENS
49
+ return false
50
+ else
51
+ return false
52
+ end
53
+ end
54
+ true
55
+ end
56
+
57
+ def syntax_error?(code)
58
+ SyntaxChecker.new(code).parse
59
+ false
60
+ rescue SyntaxChecker::ParseError
61
+ true
62
+ end
63
+ end
64
+
65
+ if defined?(Ripper)
66
+ class SyntaxChecker < Ripper
67
+ class ParseError < StandardError; end
68
+
69
+ private
70
+
71
+ def on_parse_error(*)
72
+ raise ParseError
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -1,3 +1,3 @@
1
1
  module Temple
2
- VERSION = '0.7.7'
2
+ VERSION = '0.8.0'
3
3
  end
@@ -1,15 +1,12 @@
1
1
  require 'helper'
2
- begin
3
- require 'ripper'
4
- rescue LoadError
5
- end
6
2
 
7
- if defined?(Ripper)
8
- describe Temple::Filters::StaticAnalyzer do
9
- before do
10
- @filter = Temple::Filters::StaticAnalyzer.new
11
- end
3
+ describe Temple::Filters::StaticAnalyzer do
4
+ before do
5
+ @filter = Temple::Filters::StaticAnalyzer.new
6
+ @generator = Temple::Generator.new
7
+ end
12
8
 
9
+ if Temple::StaticAnalyzer.available?
13
10
  it 'should convert :dynamic to :static if code is static' do
14
11
  @filter.call([:dynamic, '"#{"hello"}#{100}"']
15
12
  ).should.equal [:static, 'hello100']
@@ -19,5 +16,22 @@ if defined?(Ripper)
19
16
  exp = [:dynamic, '"#{hello}#{100}"']
20
17
  @filter.call(exp).should.equal(exp)
21
18
  end
19
+
20
+ it 'should not change number of newlines in generated code' do
21
+ exp = [:dynamic, "[100,\n200,\n]"]
22
+ @filter.call(exp).should.equal([:multi, [:static, '[100, 200]'], [:newline], [:newline]])
23
+
24
+ @generator.call(@filter.call(exp)).count("\n").
25
+ should.equal(@generator.call(exp).count("\n"))
26
+ end
27
+ else
28
+ it 'should do nothing' do
29
+ [
30
+ [:dynamic, '"#{"hello"}#{100}"'],
31
+ [:dynamic, '"#{hello}#{100}"'],
32
+ ].each do |exp|
33
+ @filter.call(exp).should.equal(exp)
34
+ end
35
+ end
22
36
  end
23
37
  end
@@ -14,5 +14,12 @@ if defined?(Ripper) && RUBY_VERSION >= "2.0.0"
14
14
  @filter.call([:dynamic, '"static#{dynamic}"']
15
15
  ).should.equal [:multi, [:static, 'static'], [:dynamic, 'dynamic']]
16
16
  end
17
+
18
+ describe '.compile' do
19
+ it 'should raise CompileError for non-string literals' do
20
+ lambda { Temple::Filters::StringSplitter.compile('1') }.
21
+ should.raise(Temple::FilterError)
22
+ end
23
+ end
17
24
  end
18
25
  end
@@ -0,0 +1,39 @@
1
+ require 'helper'
2
+
3
+ describe Temple::StaticAnalyzer do
4
+ describe '.available?' do
5
+ it 'should return true if its dependency is available' do
6
+ Temple::StaticAnalyzer.available?.should.equal(defined?(Ripper))
7
+ end
8
+ end
9
+
10
+ if Temple::StaticAnalyzer.available?
11
+ describe '.static?' do
12
+ it 'should return true if given Ruby expression is static' do
13
+ ['true', 'false', '"hello world"', "[1, { 2 => 3 }]", "[\n1,\n]"].each do |exp|
14
+ Temple::StaticAnalyzer.static?(exp).should.equal(true)
15
+ end
16
+ end
17
+
18
+ it 'should return false if given Ruby expression is dynamic' do
19
+ ['1 + 2', 'variable', 'method_call(a)', 'CONSTANT'].each do |exp|
20
+ Temple::StaticAnalyzer.static?(exp).should.equal(false)
21
+ end
22
+ end
23
+ end
24
+
25
+ describe '.syntax_error?' do
26
+ it 'should return false if given Ruby expression is valid' do
27
+ ['Foo.bar.baz { |c| c.d! }', '{ foo: bar }'].each do |exp|
28
+ Temple::StaticAnalyzer.syntax_error?(exp).should.equal(false)
29
+ end
30
+ end
31
+
32
+ it 'should return true if given Ruby expression is invalid' do
33
+ ['Foo.bar.baz { |c| c.d! ', ' foo: bar '].each do |exp|
34
+ Temple::StaticAnalyzer.syntax_error?(exp).should.equal(true)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: temple
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.7
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Magnus Holm
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-05-22 00:00:00.000000000 Z
12
+ date: 2017-02-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: tilt
@@ -126,6 +126,7 @@ files:
126
126
  - lib/temple/mixins/options.rb
127
127
  - lib/temple/mixins/template.rb
128
128
  - lib/temple/parser.rb
129
+ - lib/temple/static_analyzer.rb
129
130
  - lib/temple/templates.rb
130
131
  - lib/temple/templates/rails.rb
131
132
  - lib/temple/templates/tilt.rb
@@ -155,6 +156,7 @@ files:
155
156
  - test/test_generator.rb
156
157
  - test/test_grammar.rb
157
158
  - test/test_map.rb
159
+ - test/test_static_analyzer.rb
158
160
  - test/test_utils.rb
159
161
  homepage: https://github.com/judofyr/temple
160
162
  licenses:
@@ -176,8 +178,33 @@ required_rubygems_version: !ruby/object:Gem::Requirement
176
178
  version: '0'
177
179
  requirements: []
178
180
  rubyforge_project:
179
- rubygems_version: 2.2.2
181
+ rubygems_version: 2.6.8
180
182
  signing_key:
181
183
  specification_version: 4
182
184
  summary: Template compilation framework in Ruby
183
- test_files: []
185
+ test_files:
186
+ - test/filters/test_code_merger.rb
187
+ - test/filters/test_control_flow.rb
188
+ - test/filters/test_dynamic_inliner.rb
189
+ - test/filters/test_eraser.rb
190
+ - test/filters/test_escapable.rb
191
+ - test/filters/test_multi_flattener.rb
192
+ - test/filters/test_static_analyzer.rb
193
+ - test/filters/test_static_merger.rb
194
+ - test/filters/test_string_splitter.rb
195
+ - test/helper.rb
196
+ - test/html/test_attribute_merger.rb
197
+ - test/html/test_attribute_remover.rb
198
+ - test/html/test_attribute_sorter.rb
199
+ - test/html/test_fast.rb
200
+ - test/html/test_pretty.rb
201
+ - test/mixins/test_dispatcher.rb
202
+ - test/mixins/test_grammar_dsl.rb
203
+ - test/test_engine.rb
204
+ - test/test_erb.rb
205
+ - test/test_filter.rb
206
+ - test/test_generator.rb
207
+ - test/test_grammar.rb
208
+ - test/test_map.rb
209
+ - test/test_static_analyzer.rb
210
+ - test/test_utils.rb