curlybars 1.5.1 → 1.6.0
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 +4 -4
- data/lib/curlybars.rb +0 -1
- data/lib/curlybars/configuration.rb +1 -9
- data/lib/curlybars/error/base.rb +2 -0
- data/lib/curlybars/method_whitelist.rb +5 -2
- data/lib/curlybars/node/block_helper_else.rb +1 -0
- data/lib/curlybars/node/path.rb +6 -0
- data/lib/curlybars/processor/tilde.rb +3 -0
- data/lib/curlybars/rendering_support.rb +8 -0
- data/lib/curlybars/template_handler.rb +18 -6
- data/lib/curlybars/version.rb +1 -1
- data/spec/acceptance/application_layout_spec.rb +2 -2
- data/spec/acceptance/collection_blocks_spec.rb +1 -1
- data/spec/acceptance/global_helper_spec.rb +1 -1
- data/spec/curlybars/lexer_spec.rb +3 -2
- data/spec/curlybars/rendering_support_spec.rb +4 -9
- data/spec/curlybars/template_handler_spec.rb +33 -30
- data/spec/integration/cache_spec.rb +20 -18
- data/spec/integration/node/block_helper_else_spec.rb +0 -2
- data/spec/integration/node/each_else_spec.rb +0 -2
- data/spec/integration/node/each_spec.rb +0 -2
- data/spec/integration/node/helper_spec.rb +0 -2
- data/spec/integration/node/if_else_spec.rb +0 -2
- data/spec/integration/node/if_spec.rb +0 -2
- data/spec/integration/node/output_spec.rb +0 -2
- data/spec/integration/node/partial_spec.rb +0 -2
- data/spec/integration/node/path_spec.rb +0 -2
- data/spec/integration/node/root_spec.rb +0 -2
- data/spec/integration/node/sub_expression_spec.rb +0 -2
- data/spec/integration/node/template_spec.rb +0 -2
- data/spec/integration/node/unless_else_spec.rb +0 -2
- data/spec/integration/node/unless_spec.rb +0 -2
- data/spec/integration/node/with_spec.rb +0 -2
- data/spec/integration/processors_spec.rb +0 -1
- metadata +41 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2be6d03409f5c575fb33c7ba4ed74117420fd22ddca8272005c5f23e459a0d8e
|
4
|
+
data.tar.gz: ad11b01849c9d28a70b2ae2260615665cc2dc3ca3c380b9dfbc2ab9c91bf1de3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ba6035a72fd5cf75120cc3adfc663192dae68d75132887b801bd29a53c4b655f6be09ed6b8e4a2ee497e708172c38db19258215b5f3b1a9b788371db20eeac3c
|
7
|
+
data.tar.gz: 83961d2f0ef03848c1ffb3feb9db859c866ff90e74d173f116b16c3af5ff4eac710e934cd7b3bb5039749f05169bd4f95e3f19fc208163f3333a6d66ba7261df
|
data/lib/curlybars.rb
CHANGED
@@ -118,7 +118,6 @@ require 'curlybars/rendering_support'
|
|
118
118
|
require 'curlybars/parser'
|
119
119
|
require 'curlybars/position'
|
120
120
|
require 'curlybars/lexer'
|
121
|
-
require 'curlybars/parser'
|
122
121
|
require 'curlybars/processor/token_factory'
|
123
122
|
require 'curlybars/processor/tilde'
|
124
123
|
require 'curlybars/error/lex'
|
@@ -16,15 +16,7 @@ module Curlybars
|
|
16
16
|
end
|
17
17
|
|
18
18
|
class Configuration
|
19
|
-
attr_accessor :presenters_namespace
|
20
|
-
attr_accessor :nesting_limit
|
21
|
-
attr_accessor :traversing_limit
|
22
|
-
attr_accessor :output_limit
|
23
|
-
attr_accessor :rendering_timeout
|
24
|
-
attr_accessor :custom_processors
|
25
|
-
attr_accessor :compiler_transformers
|
26
|
-
attr_accessor :global_helpers_provider_classes
|
27
|
-
attr_accessor :cache
|
19
|
+
attr_accessor :presenters_namespace, :nesting_limit, :traversing_limit, :output_limit, :rendering_timeout, :custom_processors, :compiler_transformers, :global_helpers_provider_classes, :cache
|
28
20
|
|
29
21
|
def initialize
|
30
22
|
@presenters_namespace = ''
|
data/lib/curlybars/error/base.rb
CHANGED
@@ -8,8 +8,10 @@ module Curlybars
|
|
8
8
|
@id = id
|
9
9
|
@position = position
|
10
10
|
@metadata = metadata
|
11
|
+
|
11
12
|
return if position.nil?
|
12
13
|
return if position.file_name.nil?
|
14
|
+
|
13
15
|
location = "%s:%d:%d" % [position.file_name, position.line_number, position.line_offset]
|
14
16
|
set_backtrace([location])
|
15
17
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
module Curlybars
|
2
2
|
module MethodWhitelist
|
3
|
+
# rubocop:disable Style/SoleNestedConditional
|
3
4
|
def allow_methods(*methods_without_type, **methods_with_type, &contextual_block)
|
4
5
|
methods_with_type_validator = lambda do |methods_to_validate|
|
5
6
|
methods_to_validate.each do |(method_name, type)|
|
@@ -49,8 +50,8 @@ module Curlybars
|
|
49
50
|
memo[method] = nil
|
50
51
|
end
|
51
52
|
|
52
|
-
methods_with_type_resolved = all_methods_with_type.
|
53
|
-
|
53
|
+
methods_with_type_resolved = all_methods_with_type.transform_values do |type|
|
54
|
+
if type.respond_to?(:call)
|
54
55
|
type.call(context)
|
55
56
|
else
|
56
57
|
type
|
@@ -65,6 +66,7 @@ module Curlybars
|
|
65
66
|
# Included modules
|
66
67
|
included_modules.each do |mod|
|
67
68
|
next unless mod.respond_to?(:methods_schema)
|
69
|
+
|
68
70
|
schema.merge!(mod.methods_schema(context))
|
69
71
|
end
|
70
72
|
|
@@ -90,6 +92,7 @@ module Curlybars
|
|
90
92
|
allowed_methods.include?(method)
|
91
93
|
end
|
92
94
|
end
|
95
|
+
# rubocop:enable Style/SoleNestedConditional
|
93
96
|
|
94
97
|
def self.extended(base)
|
95
98
|
# define a default of no method allowed
|
@@ -100,6 +100,7 @@ module Curlybars
|
|
100
100
|
|
101
101
|
def check_open_and_close_elements(helper, helperclose, error_class)
|
102
102
|
return unless helper.path != helperclose.path
|
103
|
+
|
103
104
|
message = "block `#{helper.path}` cannot be closed by `#{helperclose.path}`"
|
104
105
|
raise error_class.new('closing_tag_mismatch', message, helperclose.position)
|
105
106
|
end
|
data/lib/curlybars/node/path.rb
CHANGED
@@ -109,26 +109,32 @@ module Curlybars
|
|
109
109
|
case check_type
|
110
110
|
when :presenter
|
111
111
|
return if presenter?(branches)
|
112
|
+
|
112
113
|
message = "`#{path}` must resolve to a presenter"
|
113
114
|
raise Curlybars::Error::Validate.new('not_a_presenter', message, position)
|
114
115
|
when :presenter_collection
|
115
116
|
return if presenter_collection?(branches)
|
117
|
+
|
116
118
|
message = "`#{path}` must resolve to a collection of presenters"
|
117
119
|
raise Curlybars::Error::Validate.new('not_a_presenter_collection', message, position)
|
118
120
|
when :leaf
|
119
121
|
return if leaf?(branches)
|
122
|
+
|
120
123
|
message = "`#{path}` cannot resolve to a component"
|
121
124
|
raise Curlybars::Error::Validate.new('not_a_leaf', message, position)
|
122
125
|
when :partial
|
123
126
|
return if partial?(branches)
|
127
|
+
|
124
128
|
message = "`#{path}` cannot resolve to a partial"
|
125
129
|
raise Curlybars::Error::Validate.new('not_a_partial', message, position)
|
126
130
|
when :helper
|
127
131
|
return if helper?(branches)
|
132
|
+
|
128
133
|
message = "`#{path}` cannot resolve to a helper"
|
129
134
|
raise Curlybars::Error::Validate.new('not_a_helper', message, position)
|
130
135
|
when :not_helper
|
131
136
|
return unless helper?(branches)
|
137
|
+
|
132
138
|
message = "`#{path}` resolves to a helper"
|
133
139
|
raise Curlybars::Error::Validate.new('is_a_helper', message, position)
|
134
140
|
when :anything
|
@@ -10,10 +10,12 @@ module Curlybars
|
|
10
10
|
when :TILDE_START
|
11
11
|
tokens[index] = create_token(:START, token.value, token.position)
|
12
12
|
next if index == 0
|
13
|
+
|
13
14
|
strip_token_if_text(tokens, index - 1, :rstrip)
|
14
15
|
when :TILDE_END
|
15
16
|
tokens[index] = create_token(:END, token.value, token.position)
|
16
17
|
next if index == (tokens.length - 1)
|
18
|
+
|
17
19
|
strip_token_if_text(tokens, index + 1, :lstrip)
|
18
20
|
end
|
19
21
|
end
|
@@ -22,6 +24,7 @@ module Curlybars
|
|
22
24
|
def strip_token_if_text(tokens, index, strip_method)
|
23
25
|
token = tokens[index]
|
24
26
|
return if token.type != :TEXT
|
27
|
+
|
25
28
|
stripped_value = token.value.public_send(strip_method)
|
26
29
|
tokens[index] = create_token(token.type, stripped_value, token.position)
|
27
30
|
end
|
@@ -23,12 +23,14 @@ module Curlybars
|
|
23
23
|
def check_timeout!
|
24
24
|
return unless timeout.present?
|
25
25
|
return unless (Time.now - start_time) > timeout
|
26
|
+
|
26
27
|
message = "Rendering took too long (> #{timeout} seconds)"
|
27
28
|
raise ::Curlybars::Error::Render.new('timeout', message, nil)
|
28
29
|
end
|
29
30
|
|
30
31
|
def check_context_is_presenter(context, path, position)
|
31
32
|
return if presenter?(context)
|
33
|
+
|
32
34
|
message = "`#{path}` is not a context type object"
|
33
35
|
raise Curlybars::Error::Render.new('context_is_not_a_presenter', message, position)
|
34
36
|
end
|
@@ -83,9 +85,11 @@ module Curlybars
|
|
83
85
|
resolved = chain.inject(base_context) do |context, meth|
|
84
86
|
next context if meth == 'this'
|
85
87
|
next context.count if meth == 'length' && presenter_collection?(context)
|
88
|
+
|
86
89
|
raise_if_not_traversable(context, meth, position)
|
87
90
|
outcome = instrument(context.method(meth)) { context.public_send(meth) }
|
88
91
|
return -> {} if outcome.nil?
|
92
|
+
|
89
93
|
outcome
|
90
94
|
end
|
91
95
|
|
@@ -101,6 +105,7 @@ module Curlybars
|
|
101
105
|
|
102
106
|
def cached_call(meth)
|
103
107
|
return cached_calls[meth] if cached_calls.key? meth
|
108
|
+
|
104
109
|
instrument(meth) { cached_calls[meth] = meth.call(*arguments_for_signature(meth, [], {})) }
|
105
110
|
end
|
106
111
|
|
@@ -202,6 +207,7 @@ module Curlybars
|
|
202
207
|
|
203
208
|
def check_context_allows_method(context, meth, position)
|
204
209
|
return if context.allows_method?(meth.to_sym)
|
210
|
+
|
205
211
|
message = "`#{meth}` is not available - "
|
206
212
|
message += "add `allow_methods :#{meth}` to #{context.class} to allow this path"
|
207
213
|
raise Curlybars::Error::Render.new('unallowed_path', message, position, meth: meth.to_sym)
|
@@ -209,12 +215,14 @@ module Curlybars
|
|
209
215
|
|
210
216
|
def check_context_has_method(context, meth, position)
|
211
217
|
return if context.respond_to?(meth.to_sym)
|
218
|
+
|
212
219
|
message = "`#{meth}` is not available in #{context.class}"
|
213
220
|
raise Curlybars::Error::Render.new('unallowed_path', message, position)
|
214
221
|
end
|
215
222
|
|
216
223
|
def check_traverse_not_too_deep(traverse, position)
|
217
224
|
return unless traverse.count('.') > Curlybars.configuration.traversing_limit
|
225
|
+
|
218
226
|
message = "`#{traverse}` too deep"
|
219
227
|
raise Curlybars::Error::Render.new('traverse_too_deep', message, position)
|
220
228
|
end
|
@@ -13,9 +13,17 @@ module Curlybars
|
|
13
13
|
# template - The ActionView::Template template that should be compiled.
|
14
14
|
#
|
15
15
|
# Returns a String containing the Ruby code representing the template.
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
if ActionView::VERSION::MAJOR < 6
|
17
|
+
def call(template)
|
18
|
+
instrument(template) do
|
19
|
+
compile_for_actionview5(template)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
else
|
23
|
+
def call(template, source)
|
24
|
+
instrument(template) do
|
25
|
+
compile(template, source)
|
26
|
+
end
|
19
27
|
end
|
20
28
|
end
|
21
29
|
|
@@ -43,9 +51,13 @@ module Curlybars
|
|
43
51
|
|
44
52
|
private
|
45
53
|
|
46
|
-
def
|
54
|
+
def compile_for_actionview5(template)
|
55
|
+
compile(template, template.source)
|
56
|
+
end
|
57
|
+
|
58
|
+
def compile(template, source)
|
47
59
|
# Template is empty, so there's no need to initialize a presenter.
|
48
|
-
return %("") if
|
60
|
+
return %("") if source.empty?
|
49
61
|
|
50
62
|
path = template.virtual_path
|
51
63
|
presenter_class = Curlybars::Presenter.presenter_for_path(path)
|
@@ -55,7 +67,7 @@ module Curlybars
|
|
55
67
|
# For security reason, we strip the encoding directive in order to avoid
|
56
68
|
# potential issues when rendering the template in another character
|
57
69
|
# encoding.
|
58
|
-
safe_source =
|
70
|
+
safe_source = source.gsub(/\A#{ActionView::ENCODING_FLAG}/, '')
|
59
71
|
|
60
72
|
source = Curlybars.compile(safe_source, template.identifier)
|
61
73
|
|
data/lib/curlybars/version.rb
CHANGED
@@ -2,7 +2,7 @@ describe "Using Curlybars for the application layout", type: :request do
|
|
2
2
|
example "A simple layout view in Curlybars" do
|
3
3
|
get '/'
|
4
4
|
|
5
|
-
expect(body).to eq(
|
5
|
+
expect(body).to eq(<<~HTML)
|
6
6
|
<html>
|
7
7
|
<head>
|
8
8
|
<title>Dummy app</title>
|
@@ -31,7 +31,7 @@ describe "Using Curlybars for the application layout", type: :request do
|
|
31
31
|
example "A simple layout view in Curlybars with html safe logic" do
|
32
32
|
get '/articles/1'
|
33
33
|
|
34
|
-
expect(body).to eq(
|
34
|
+
expect(body).to eq(<<~HTML)
|
35
35
|
<html>
|
36
36
|
<head>
|
37
37
|
<title>Dummy app</title>
|
@@ -37,6 +37,7 @@ describe Curlybars::Lexer do
|
|
37
37
|
it "is resilient to whitespaces" do
|
38
38
|
expect(lex('{{! }}')).to produce []
|
39
39
|
end
|
40
|
+
|
40
41
|
it "is resilient to newlines" do
|
41
42
|
expect(lex("{{!\n}}")).to produce []
|
42
43
|
end
|
@@ -202,7 +203,7 @@ describe Curlybars::Lexer do
|
|
202
203
|
end
|
203
204
|
end
|
204
205
|
|
205
|
-
# rubocop:disable Layout/
|
206
|
+
# rubocop:disable Layout/ArrayAlignment
|
206
207
|
describe "{{#if path}}...{{else}}...{{/if}}" do
|
207
208
|
it "is lexed" do
|
208
209
|
expect(lex('{{#if path}} text {{else}} text {{/if}}')).to produce(
|
@@ -320,7 +321,7 @@ describe Curlybars::Lexer do
|
|
320
321
|
)
|
321
322
|
end
|
322
323
|
end
|
323
|
-
# rubocop:enable Layout/
|
324
|
+
# rubocop:enable Layout/ArrayAlignment
|
324
325
|
|
325
326
|
describe "{{#with path}}...{{/with}}" do
|
326
327
|
it "is lexed" do
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# rubocop:disable RSpec/MultipleMemoizedHelpers
|
1
2
|
describe Curlybars::RenderingSupport do
|
2
3
|
let(:file_name) { '/app/views/template.hbs' }
|
3
4
|
let(:presenter) { double(:presenter, allows_method?: true, meth: :value) }
|
@@ -7,7 +8,6 @@ describe Curlybars::RenderingSupport do
|
|
7
8
|
let(:position) do
|
8
9
|
double(:position, file_name: 'template.hbs', line_number: 1, line_offset: 0)
|
9
10
|
end
|
10
|
-
let(:block) { -> {} }
|
11
11
|
|
12
12
|
describe "#check_timeout!" do
|
13
13
|
it "skips checking if timeout is nil" do
|
@@ -179,14 +179,6 @@ describe Curlybars::RenderingSupport do
|
|
179
179
|
end
|
180
180
|
|
181
181
|
describe "#cached_call" do
|
182
|
-
before do
|
183
|
-
class APresenter
|
184
|
-
def meth
|
185
|
-
:value
|
186
|
-
end
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
182
|
it "(cache miss) calls the method if not cached already" do
|
191
183
|
meth = presenter.method(:meth)
|
192
184
|
allow(meth).to receive(:call)
|
@@ -217,6 +209,8 @@ describe Curlybars::RenderingSupport do
|
|
217
209
|
end
|
218
210
|
|
219
211
|
describe "#call" do
|
212
|
+
let(:block) { -> {} }
|
213
|
+
|
220
214
|
it "calls with no arguments a method with no parameters" do
|
221
215
|
method = -> { :return }
|
222
216
|
arguments = []
|
@@ -424,3 +418,4 @@ describe Curlybars::RenderingSupport do
|
|
424
418
|
allow(presenter).to receive(:allows_method?).and_return(false)
|
425
419
|
end
|
426
420
|
end
|
421
|
+
# rubocop:enable RSpec/MultipleMemoizedHelpers
|
@@ -100,13 +100,11 @@ describe Curlybars::TemplateHandler do
|
|
100
100
|
end
|
101
101
|
|
102
102
|
it "strips the `# encoding: *` directive away from the template" do
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
end
|
109
|
-
expect(output).to eq(<<-TEMPLATE.strip_heredoc)
|
103
|
+
output = render(<<~TEMPLATE)
|
104
|
+
# encoding: utf-8"
|
105
|
+
first line
|
106
|
+
TEMPLATE
|
107
|
+
expect(output).to eq(<<~TEMPLATE)
|
110
108
|
|
111
109
|
first line
|
112
110
|
TEMPLATE
|
@@ -114,55 +112,54 @@ describe Curlybars::TemplateHandler do
|
|
114
112
|
|
115
113
|
it "passes in the presenter context to the presenter class" do
|
116
114
|
allow(context).to receive(:bar).and_return("BAR")
|
117
|
-
|
115
|
+
output = render("{{bar}}")
|
118
116
|
expect(output).to eq("BAR")
|
119
117
|
end
|
120
118
|
|
121
119
|
it "fails if there's no matching presenter class" do
|
122
120
|
allow(template).to receive(:virtual_path).and_return("missing")
|
123
|
-
|
124
|
-
expect { output }.to raise_exception(Curlybars::Error::Presenter::NotFound)
|
121
|
+
expect { render(" FOO ") }.to raise_exception(Curlybars::Error::Presenter::NotFound)
|
125
122
|
end
|
126
123
|
|
127
124
|
it "allows calling public methods on the presenter" do
|
128
|
-
|
125
|
+
output = render("{{foo}}")
|
129
126
|
expect(output).to eq("FOO")
|
130
127
|
end
|
131
128
|
|
132
129
|
it "marks its output as HTML safe" do
|
133
|
-
|
130
|
+
output = render("{{foo}}")
|
134
131
|
expect(output).to be_html_safe
|
135
132
|
end
|
136
133
|
|
137
134
|
it "calls the #setup! method before rendering the view" do
|
138
|
-
|
139
|
-
output
|
135
|
+
render("{{foo}}")
|
140
136
|
expect(context.content_for(:foo)).to eq("bar")
|
141
137
|
end
|
142
138
|
|
143
139
|
describe "caching" do
|
144
140
|
before do
|
145
|
-
allow(template).to receive(:source).and_return("{{bar}}")
|
146
141
|
allow(context).to receive(:bar).and_return("BAR")
|
147
142
|
end
|
148
143
|
|
144
|
+
let(:output) { -> { render("{{bar}}") } }
|
145
|
+
|
149
146
|
it "caches the result with the #cache_key from the presenter" do
|
150
147
|
context.assigns[:cache_key] = "x"
|
151
|
-
expect(output).to eq("BAR")
|
148
|
+
expect(output.call).to eq("BAR")
|
152
149
|
|
153
150
|
allow(context).to receive(:bar).and_return("BAZ")
|
154
|
-
expect(output).to eq("BAR")
|
151
|
+
expect(output.call).to eq("BAR")
|
155
152
|
|
156
153
|
context.assigns[:cache_key] = "y"
|
157
|
-
expect(output).to eq("BAZ")
|
154
|
+
expect(output.call).to eq("BAZ")
|
158
155
|
end
|
159
156
|
|
160
157
|
it "doesn't cache when the cache key is nil" do
|
161
158
|
context.assigns[:cache_key] = nil
|
162
|
-
expect(output).to eq("BAR")
|
159
|
+
expect(output.call).to eq("BAR")
|
163
160
|
|
164
161
|
allow(context).to receive(:bar).and_return("BAZ")
|
165
|
-
expect(output).to eq("BAZ")
|
162
|
+
expect(output.call).to eq("BAZ")
|
166
163
|
end
|
167
164
|
|
168
165
|
it "adds the presenter class' cache key to the instance's cache key" do
|
@@ -171,51 +168,57 @@ describe Curlybars::TemplateHandler do
|
|
171
168
|
|
172
169
|
allow(presenter_class).to receive(:cache_key).and_return("foo")
|
173
170
|
|
174
|
-
expect(output).to eq("BAR")
|
171
|
+
expect(output.call).to eq("BAR")
|
175
172
|
|
176
173
|
allow(presenter_class).to receive(:cache_key).and_return("bar")
|
177
174
|
|
178
175
|
allow(context).to receive(:bar).and_return("FOOBAR")
|
179
|
-
expect(output).to eq("FOOBAR")
|
176
|
+
expect(output.call).to eq("FOOBAR")
|
180
177
|
end
|
181
178
|
|
182
179
|
it "expires the cache keys after #cache_duration" do
|
183
180
|
context.assigns[:cache_key] = "x"
|
184
181
|
context.assigns[:cache_duration] = 42
|
185
182
|
|
186
|
-
expect(output).to eq("BAR")
|
183
|
+
expect(output.call).to eq("BAR")
|
187
184
|
|
188
185
|
allow(context).to receive(:bar).and_return("FOO")
|
189
186
|
|
190
187
|
# Cached fragment has not yet expired.
|
191
188
|
context.advance_clock(41)
|
192
|
-
expect(output).to eq("BAR")
|
189
|
+
expect(output.call).to eq("BAR")
|
193
190
|
|
194
191
|
# Now it has! Huzzah!
|
195
192
|
context.advance_clock(1)
|
196
|
-
expect(output).to eq("FOO")
|
193
|
+
expect(output.call).to eq("FOO")
|
197
194
|
end
|
198
195
|
|
199
196
|
it "passes #cache_options to the cache backend" do
|
200
197
|
context.assigns[:cache_key] = "x"
|
201
198
|
context.assigns[:cache_options] = { expires_in: 42 }
|
202
199
|
|
203
|
-
expect(output).to eq("BAR")
|
200
|
+
expect(output.call).to eq("BAR")
|
204
201
|
|
205
202
|
allow(context).to receive(:bar).and_return("FOO")
|
206
203
|
|
207
204
|
# Cached fragment has not yet expired.
|
208
205
|
context.advance_clock(41)
|
209
|
-
expect(output).to eq("BAR")
|
206
|
+
expect(output.call).to eq("BAR")
|
210
207
|
|
211
208
|
# Now it has! Huzzah!
|
212
209
|
context.advance_clock(1)
|
213
|
-
expect(output).to eq("FOO")
|
210
|
+
expect(output.call).to eq("FOO")
|
214
211
|
end
|
215
212
|
end
|
216
213
|
|
217
|
-
def
|
218
|
-
|
214
|
+
def render(source)
|
215
|
+
if ActionView::VERSION::MAJOR < 6
|
216
|
+
allow(template).to receive(:source).and_return(source)
|
217
|
+
code = Curlybars::TemplateHandler.call(template)
|
218
|
+
else
|
219
|
+
code = Curlybars::TemplateHandler.call(template, source)
|
220
|
+
end
|
221
|
+
|
219
222
|
context.reset!
|
220
223
|
context.instance_eval(code)
|
221
224
|
end
|
@@ -1,29 +1,31 @@
|
|
1
1
|
describe "caching" do
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
2
|
+
let(:dummy_cache) do
|
3
|
+
Class.new do
|
4
|
+
attr_reader :reads, :hits
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@store = {}
|
8
|
+
@reads = 0
|
9
|
+
@hits = 0
|
10
|
+
end
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
12
|
+
def fetch(key)
|
13
|
+
@reads += 1
|
14
|
+
if @store.key?(key)
|
15
|
+
@hits += 1
|
16
|
+
@store[key]
|
17
|
+
else
|
18
|
+
value = yield
|
19
|
+
@store[key] = value
|
20
|
+
value
|
21
|
+
end
|
20
22
|
end
|
21
23
|
end
|
22
24
|
end
|
23
25
|
|
24
26
|
let(:global_helpers_providers) { [] }
|
25
27
|
let(:presenter) { IntegrationTest::Presenter.new(double("view_context")) }
|
26
|
-
let(:cache) {
|
28
|
+
let(:cache) { dummy_cache.new }
|
27
29
|
|
28
30
|
before do
|
29
31
|
Curlybars.configure do |config|
|
@@ -230,8 +230,6 @@ describe "{{#helper arg1 arg2 ... key=value ...}}...<{{else}}>...{{/helper}}" do
|
|
230
230
|
end
|
231
231
|
|
232
232
|
describe "#validate" do
|
233
|
-
let(:presenter_class) { double(:presenter_class) }
|
234
|
-
|
235
233
|
it "without errors when global helper" do
|
236
234
|
allow(Curlybars.configuration).to receive(:global_helpers_provider_classes).and_return([IntegrationTest::GlobalHelperProvider])
|
237
235
|
|
@@ -227,8 +227,6 @@ describe "{{(helper arg1 arg2 ... key=value ...)}}" do
|
|
227
227
|
end
|
228
228
|
|
229
229
|
describe "#validate" do
|
230
|
-
let(:presenter_class) { double(:presenter_class) }
|
231
|
-
|
232
230
|
before do
|
233
231
|
allow(Curlybars.configuration).to receive(:global_helpers_provider_classes).and_return([IntegrationTest::GlobalHelperProvider])
|
234
232
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: curlybars
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Libo Cannici
|
@@ -14,7 +14,7 @@ authors:
|
|
14
14
|
autorequire:
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
|
-
date:
|
17
|
+
date: 2021-01-05 00:00:00.000000000 Z
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
20
20
|
name: actionpack
|
@@ -25,7 +25,7 @@ dependencies:
|
|
25
25
|
version: '4.2'
|
26
26
|
- - "<"
|
27
27
|
- !ruby/object:Gem::Version
|
28
|
-
version: '6.
|
28
|
+
version: '6.2'
|
29
29
|
type: :runtime
|
30
30
|
prerelease: false
|
31
31
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -35,7 +35,7 @@ dependencies:
|
|
35
35
|
version: '4.2'
|
36
36
|
- - "<"
|
37
37
|
- !ruby/object:Gem::Version
|
38
|
-
version: '6.
|
38
|
+
version: '6.2'
|
39
39
|
- !ruby/object:Gem::Dependency
|
40
40
|
name: activesupport
|
41
41
|
requirement: !ruby/object:Gem::Requirement
|
@@ -45,7 +45,7 @@ dependencies:
|
|
45
45
|
version: '4.2'
|
46
46
|
- - "<"
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version: '6.
|
48
|
+
version: '6.2'
|
49
49
|
type: :runtime
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -55,7 +55,7 @@ dependencies:
|
|
55
55
|
version: '4.2'
|
56
56
|
- - "<"
|
57
57
|
- !ruby/object:Gem::Version
|
58
|
-
version: '6.
|
58
|
+
version: '6.2'
|
59
59
|
- !ruby/object:Gem::Dependency
|
60
60
|
name: ffi
|
61
61
|
requirement: !ruby/object:Gem::Requirement
|
@@ -121,7 +121,7 @@ dependencies:
|
|
121
121
|
version: '4.2'
|
122
122
|
- - "<"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: '6.
|
124
|
+
version: '6.2'
|
125
125
|
type: :development
|
126
126
|
prerelease: false
|
127
127
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -131,7 +131,7 @@ dependencies:
|
|
131
131
|
version: '4.2'
|
132
132
|
- - "<"
|
133
133
|
- !ruby/object:Gem::Version
|
134
|
-
version: '6.
|
134
|
+
version: '6.2'
|
135
135
|
- !ruby/object:Gem::Dependency
|
136
136
|
name: rake
|
137
137
|
requirement: !ruby/object:Gem::Requirement
|
@@ -166,28 +166,56 @@ dependencies:
|
|
166
166
|
requirements:
|
167
167
|
- - "~>"
|
168
168
|
- !ruby/object:Gem::Version
|
169
|
-
version:
|
169
|
+
version: 1.6.0
|
170
170
|
type: :development
|
171
171
|
prerelease: false
|
172
172
|
version_requirements: !ruby/object:Gem::Requirement
|
173
173
|
requirements:
|
174
174
|
- - "~>"
|
175
175
|
- !ruby/object:Gem::Version
|
176
|
-
version:
|
176
|
+
version: 1.6.0
|
177
|
+
- !ruby/object:Gem::Dependency
|
178
|
+
name: rubocop-performance
|
179
|
+
requirement: !ruby/object:Gem::Requirement
|
180
|
+
requirements:
|
181
|
+
- - "~>"
|
182
|
+
- !ruby/object:Gem::Version
|
183
|
+
version: 1.9.0
|
184
|
+
type: :development
|
185
|
+
prerelease: false
|
186
|
+
version_requirements: !ruby/object:Gem::Requirement
|
187
|
+
requirements:
|
188
|
+
- - "~>"
|
189
|
+
- !ruby/object:Gem::Version
|
190
|
+
version: 1.9.0
|
191
|
+
- !ruby/object:Gem::Dependency
|
192
|
+
name: rubocop-rake
|
193
|
+
requirement: !ruby/object:Gem::Requirement
|
194
|
+
requirements:
|
195
|
+
- - "~>"
|
196
|
+
- !ruby/object:Gem::Version
|
197
|
+
version: 0.5.0
|
198
|
+
type: :development
|
199
|
+
prerelease: false
|
200
|
+
version_requirements: !ruby/object:Gem::Requirement
|
201
|
+
requirements:
|
202
|
+
- - "~>"
|
203
|
+
- !ruby/object:Gem::Version
|
204
|
+
version: 0.5.0
|
177
205
|
- !ruby/object:Gem::Dependency
|
178
206
|
name: rubocop-rspec
|
179
207
|
requirement: !ruby/object:Gem::Requirement
|
180
208
|
requirements:
|
181
209
|
- - "~>"
|
182
210
|
- !ruby/object:Gem::Version
|
183
|
-
version: 1.
|
211
|
+
version: 2.1.0
|
184
212
|
type: :development
|
185
213
|
prerelease: false
|
186
214
|
version_requirements: !ruby/object:Gem::Requirement
|
187
215
|
requirements:
|
188
216
|
- - "~>"
|
189
217
|
- !ruby/object:Gem::Version
|
190
|
-
version: 1.
|
218
|
+
version: 2.1.0
|
191
219
|
description: |-
|
192
220
|
A view layer for your Rails apps that separates structure and logic, using Handlebars templates.
|
193
221
|
Strongly inspired by Curly Template gem by Daniel Schierbeck.
|
@@ -288,7 +316,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
288
316
|
requirements:
|
289
317
|
- - ">="
|
290
318
|
- !ruby/object:Gem::Version
|
291
|
-
version: '
|
319
|
+
version: '2.4'
|
292
320
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
293
321
|
requirements:
|
294
322
|
- - ">="
|