template-ruby 0.2.0 → 0.2.3

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: f42cd4f03c1c1bacdfdcc9e454cdc19411220aa407698bc63024f59311d0a23f
4
- data.tar.gz: 59da1aed5e7e8e729c1c4a44c36c62fcaacc47780229e61b8606708e1414e4c4
3
+ metadata.gz: d5e2a863316056d011b034cc0c819984d710899e8b51657dd15636e45db058b0
4
+ data.tar.gz: 47974cad2e705fb70706b68a496523f414b3027c6f57ec6d22344c588cdce143
5
5
  SHA512:
6
- metadata.gz: 4e56e63c45fce924c3b62571a58be48846be2a0348565713a2e5de6f6a33f07d15ce4e37fc0d48a3ef964ff3d8cb8810bff55ae6f2cc5bba184df2b14182d85c
7
- data.tar.gz: 26ba43eea5b6d61a99fd358bdcded3bfcc52e0b0b57910c62f0773380f3777a4b29b8ff355937c0d716cdd5f4e7d29561d17c642de1476a06a32fdd798c3d6ad
6
+ metadata.gz: 1ba52300910fb32458e115c200842c3a2ef18a19e8fddee92c38a961d60637d3c3c73906304184ef0ec5771ad85cc5dd19d8dbe0803a872a2c5c0dd69cc82a16
7
+ data.tar.gz: d526bbd95df4375aee06d4c9cc8bb8c6f2927b725514527dd9d3e29229223235bf0c8870d917eb61ae30cbce52e2c27a5f18ba31a2b1fcc94b0dfc574bf77bd1
data/CHANGELOG.md CHANGED
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## 0.2.3 / 2022-08-31
9
+
10
+ - Add default timeout for code and template parsing and evaluation
11
+
12
+ ## 0.2.2 / 2022-08-31
13
+
14
+ - Fix parsing error when the template is empty, e.g. ""
15
+
16
+ ## 0.2.1 / 2022-08-31
17
+
18
+ - Fix parsing error on empty code like `Hello {`
19
+
8
20
  ## 0.2.0 / 2022-08-30
9
21
 
10
22
  - Programming language capable of solving the first 5 Project Euler problems
@@ -12,4 +24,3 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
12
24
  ## 0.1.0 / 2022-07-28
13
25
 
14
26
  - Initial version with interpolation
15
-
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- template-ruby (0.1.0)
4
+ template-ruby (0.2.2)
5
5
  activesupport (~> 7)
6
6
  parslet (~> 2)
7
7
  zeitwerk (~> 2.6)
@@ -21,7 +21,7 @@ GEM
21
21
  tilt
22
22
  i18n (1.12.0)
23
23
  concurrent-ruby (~> 1.0)
24
- minitest (5.16.2)
24
+ minitest (5.16.3)
25
25
  parslet (2.0.0)
26
26
  prettier (3.2.0)
27
27
  syntax_tree (>= 2.7.1)
@@ -42,9 +42,9 @@ GEM
42
42
  diff-lcs (>= 1.2.0, < 2.0)
43
43
  rspec-support (~> 3.11.0)
44
44
  rspec-support (3.11.0)
45
- syntax_tree (3.2.1)
45
+ syntax_tree (3.5.0)
46
46
  prettier_print
47
- syntax_tree-haml (1.3.0)
47
+ syntax_tree-haml (1.3.1)
48
48
  haml (>= 5.2)
49
49
  prettier_print
50
50
  syntax_tree (>= 2.0.1)
@@ -8,9 +8,10 @@ class Code
8
8
  @arguments.map! { |argument| ::Code::Node::CallArgument.new(argument) }
9
9
 
10
10
  if call.key?(:right)
11
- @right = call.fetch(:right).map do |right|
12
- ::Code::Node::ChainedCall.new(right)
13
- end
11
+ @right =
12
+ call
13
+ .fetch(:right)
14
+ .map { |right| ::Code::Node::ChainedCall.new(right) }
14
15
  end
15
16
 
16
17
  if call.key?(:block)
@@ -59,7 +59,7 @@ class Code
59
59
  else
60
60
  acc + [element]
61
61
  end
62
- end
62
+ end,
63
63
  )
64
64
  end
65
65
 
@@ -138,7 +138,7 @@ class Code
138
138
  argument.call(
139
139
  arguments: [
140
140
  ::Code::Object::Argument.new(acc),
141
- ::Code::Object::Argument.new(element)
141
+ ::Code::Object::Argument.new(element),
142
142
  ],
143
143
  context: context,
144
144
  io: io,
@@ -169,7 +169,7 @@ class Code
169
169
  context: context,
170
170
  io: io,
171
171
  ).truthy?
172
- end
172
+ end,
173
173
  )
174
174
  end
175
175
 
@@ -183,7 +183,7 @@ class Code
183
183
  context: context,
184
184
  io: io,
185
185
  )
186
- end
186
+ end,
187
187
  )
188
188
  end
189
189
 
@@ -54,13 +54,11 @@ class Code
54
54
  argument = arguments.first.value
55
55
  ::Code::Object::Boolean.new(
56
56
  raw.any? do |element|
57
- argument
58
- .call(
59
- arguments: [::Code::Object::Argument.new(element)],
60
- context: context,
61
- io: io,
62
- )
63
- .truthy?
57
+ argument.call(
58
+ arguments: [::Code::Object::Argument.new(element)],
59
+ context: context,
60
+ io: io,
61
+ ).truthy?
64
62
  end,
65
63
  )
66
64
  end
@@ -70,13 +68,11 @@ class Code
70
68
  argument = arguments.first.value
71
69
  ::Code::Object::Boolean.new(
72
70
  raw.all? do |element|
73
- argument
74
- .call(
75
- arguments: [::Code::Object::Argument.new(element)],
76
- context: context,
77
- io: io,
78
- )
79
- .truthy?
71
+ argument.call(
72
+ arguments: [::Code::Object::Argument.new(element)],
73
+ context: context,
74
+ io: io,
75
+ ).truthy?
80
76
  end,
81
77
  )
82
78
  end
@@ -104,7 +100,7 @@ class Code
104
100
  context: context,
105
101
  io: io,
106
102
  ).truthy?
107
- end
103
+ end,
108
104
  )
109
105
  end
110
106
 
@@ -118,7 +114,7 @@ class Code
118
114
  context: context,
119
115
  io: io,
120
116
  )
121
- end
117
+ end,
122
118
  )
123
119
  end
124
120
 
@@ -131,9 +127,13 @@ class Code
131
127
  list << element
132
128
 
133
129
  if @exlucde_end
134
- list << element while (element = element + argument) < @right
130
+ while (element = element + argument) < @right
131
+ list << element
132
+ end
135
133
  else
136
- list << element while (element = element + argument) <= @right
134
+ while (element = element + argument) <= @right
135
+ list << element
136
+ end
137
137
  end
138
138
 
139
139
  list
data/lib/code/object.rb CHANGED
@@ -45,11 +45,7 @@ class Code
45
45
 
46
46
  def <=>(other)
47
47
  if respond_to?(:raw)
48
- if other.respond_to?(:raw)
49
- raw <=> other.raw
50
- else
51
- raw <=> other
52
- end
48
+ other.respond_to?(:raw) ? raw <=> other.raw : raw <=> other
53
49
  else
54
50
  other <=> self
55
51
  end
@@ -57,11 +53,7 @@ class Code
57
53
 
58
54
  def ==(other)
59
55
  if respond_to?(:raw)
60
- if other.respond_to?(:raw)
61
- raw == other.raw
62
- else
63
- raw == other
64
- end
56
+ other.respond_to?(:raw) ? raw == other.raw : raw == other
65
57
  else
66
58
  other == self
67
59
  end
@@ -9,7 +9,8 @@ class Code
9
9
  rule(:whitespace?) { whitespace.maybe }
10
10
 
11
11
  rule(:code) do
12
- (whitespace? >> statement >> whitespace?).repeat(1) | whitespace?
12
+ (whitespace?.ignore >> statement >> whitespace?.ignore).repeat(1) |
13
+ whitespace?.ignore
13
14
  end
14
15
 
15
16
  root(:code)
data/lib/code.rb CHANGED
@@ -1,22 +1,27 @@
1
1
  class Code
2
- def initialize(input, io: $stdout)
2
+ def initialize(input, io: $stdout, timeout: 10)
3
3
  @input = input
4
- @parsed = ::Code::Parser::Code.new.parse(@input)
4
+ @parsed = Timeout::timeout(timeout) do
5
+ ::Code::Parser::Code.new.parse(@input)
6
+ end
5
7
  @io = io
8
+ @timeout = timeout
6
9
  end
7
10
 
8
- def self.evaluate(input, context = "", io: $stdout)
9
- new(input, io: io).evaluate(context)
11
+ def self.evaluate(input, context = "", io: $stdout, timeout: 10)
12
+ new(input, io: io, timeout: timeout).evaluate(context)
10
13
  end
11
14
 
12
15
  def evaluate(context = "")
13
- if context.present?
14
- context = ::Code.evaluate(context)
15
- else
16
- context = ::Code::Object::Dictionnary.new
17
- end
16
+ Timeout::timeout(@timeout) do
17
+ if context.present?
18
+ context = ::Code.evaluate(context, timeout: @timeout)
19
+ else
20
+ context = ::Code::Object::Dictionnary.new
21
+ end
18
22
 
19
- ::Code::Node::Code.new(parsed).evaluate(context: context, io: @io)
23
+ ::Code::Node::Code.new(parsed).evaluate(context: context, io: @io)
24
+ end
20
25
  end
21
26
 
22
27
  private
@@ -15,10 +15,14 @@ class Template
15
15
  end
16
16
 
17
17
  rule(:code_part) do
18
- left_curly_bracket >> code >> (right_curly_bracket | any.absent?)
18
+ left_curly_bracket.ignore >> code >>
19
+ (right_curly_bracket.ignore | any.absent?)
19
20
  end
20
21
 
21
- rule(:template) { (text_part.as(:text) | code_part.as(:code)).repeat(1) }
22
+ rule(:template) do
23
+ (text_part.as(:text) | code_part.as(:code)).repeat(1) |
24
+ str("").as(:text).repeat(1, 1)
25
+ end
22
26
 
23
27
  root(:template)
24
28
  end
data/lib/template-ruby.rb CHANGED
@@ -4,6 +4,7 @@ require "bigdecimal"
4
4
  require "active_support"
5
5
  require "active_support/core_ext/object/blank"
6
6
  require "stringio"
7
+ require "timeout"
7
8
 
8
9
  loader = Zeitwerk::Loader.for_gem(warn_on_extra_files: false)
9
10
  loader.ignore(__FILE__)
data/lib/template.rb CHANGED
@@ -1,25 +1,30 @@
1
1
  class Template
2
- VERSION = Gem::Version.new("0.2.0")
2
+ VERSION = Gem::Version.new("0.2.3")
3
3
 
4
- def initialize(input, io: StringIO.new)
4
+ def initialize(input, io: StringIO.new, timeout: 10)
5
5
  @input = input
6
- @parsed = ::Template::Parser::Template.new.parse(@input)
6
+ @parsed = Timeout::timeout(timeout) do
7
+ ::Template::Parser::Template.new.parse(@input)
8
+ end
7
9
  @io = io
10
+ @timeout = timeout
8
11
  end
9
12
 
10
- def self.render(input, context = "", io: StringIO.new)
11
- new(input, io: io).render(context)
13
+ def self.render(input, context = "", io: StringIO.new, timeout: 10)
14
+ new(input, io: io, timeout: timeout).render(context)
12
15
  end
13
16
 
14
17
  def render(context = "")
15
- if context.present?
16
- context = ::Code.evaluate(context)
17
- else
18
- context = ::Code::Object::Dictionnary.new
19
- end
18
+ Timeout::timeout(@timeout) do
19
+ if context.present?
20
+ context = ::Code.evaluate(context, timeout: @timeout)
21
+ else
22
+ context = ::Code::Object::Dictionnary.new
23
+ end
20
24
 
21
- ::Template::Node::Template.new(@parsed).evaluate(context: context, io: @io)
25
+ ::Template::Node::Template.new(@parsed).evaluate(context: context, io: @io)
22
26
 
23
- @io.is_a?(StringIO) ? @io.string : nil
27
+ @io.is_a?(StringIO) ? @io.string : nil
28
+ end
24
29
  end
25
30
  end
@@ -21,9 +21,7 @@ RSpec.describe Code::Parser::Call do
21
21
  },
22
22
  },
23
23
  },
24
- right: [{
25
- name: "times",
26
- }],
24
+ right: [{ name: "times" }],
27
25
  },
28
26
  },
29
27
  ],
@@ -12,11 +12,8 @@ RSpec.describe Template do
12
12
  '{ user: { first_name: "Dorian" } }',
13
13
  "Hello Dorian",
14
14
  ],
15
- [<<~TEMPLATE, "", ""]
16
- {
17
- until true
18
- end
19
- TEMPLATE
15
+ ["Hello {", "", "Hello "],
16
+ ["", "", ""],
20
17
  ].each do |(input, input_context, expected)|
21
18
  context "#{input.inspect} #{input_context.inspect}" do
22
19
  let(:input) { input }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: template-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dorian Marié
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-30 00:00:00.000000000 Z
11
+ date: 2022-08-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport